概要
INTRODUCTION
更多信息
创建 Visual C# InfoPath 2003 项目
1. | 启动 Microsoft Visual Studio NET 2003。 |
2. | 在 文件 菜单上, 单击 新建 , 并单击 项目 。 |
3. | 在 新项目 对话框中, 单击 Microsoft Office InfoPath 项目文件夹中 Visual C# 项目 。 |
4. | 在 名称 框中, 键入 AttachmentEncoding , 然后单击 确定 。 |
5. | 在 MicrosoftOffice 项目向导, 单击 创建新表单模板 , 然后单击 完成 。
MicrosoftOffice 项目向导创建新 Visual Studio NET 2003 项目名 AttachmentEncoding。 还创建 InfoPath 表单模板。 InfoPath 表单模板名为 AttachmentEncoding。 |
在 Visual Studio NET 2003 创建编码器类
1. | 右击 AttachmentEncoding 在 SolutionExplorer@@, 指向 添加 , 并然后单击 @ @ @ AddNewItem@@@ 。 |
2. | 单击 模板 窗格中 类 AddNewItem@@ @ 对话框中, 在 名称 框中, 键入 InfoPathAttachmentEncoder.cs , 然后单击 打开 。 |
3. | 用以下代码替换 InfoPathAttachmentEncoder.cs 文件中所有代码。
using System; using System.IO; using System.Text; using System.Security.Cryptography; namespace InfoPathAttachmentEncoding { /// <summary> /// InfoPathAttachment encodes file data into the format expected by InfoPath for use in file attachment nodes. /// </summary> public class InfoPathAttachmentEncoder { private string base64EncodedFile = string.Empty; private string fullyQualifiedFileName; /// <summary> /// Creates an encoder to create an InfoPath attachment string. /// </summary> /// <param name="fullyQualifiedFileName"></param> public InfoPathAttachmentEncoder(string fullyQualifiedFileName) { if (fullyQualifiedFileName == string.Empty) throw new ArgumentException("Must specify file name", "fullyQualifiedFileName"); if (!File.Exists(fullyQualifiedFileName)) throw new FileNotFoundException("File does not exist: " + fullyQualifiedFileName, fullyQualifiedFileName); this.fullyQualifiedFileName = fullyQualifiedFileName; } /// <summary> /// Returns a Base64 encoded string. /// </summary> /// <returns>String</returns> public string ToBase64String() { if (base64EncodedFile != string.Empty) return base64EncodedFile; // This memory stream will hold the InfoPath file attachment buffer before Base64 encoding. MemoryStream ms = new MemoryStream(); // Get the file information. using (BinaryReader br = new BinaryReader(File.Open(fullyQualifiedFileName, FileMode.Open, FileAccess.Read, FileShare.Read))) { string fileName = Path.GetFileName(fullyQualifiedFileName); uint fileNameLength = (uint)fileName.Length + 1; byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName); using (BinaryWriter bw = new BinaryWriter(ms)) { // Write the InfoPath attachment signature. bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 }); // Write the default header information. bw.Write((uint)0x14); // size bw.Write((uint)0x01); // version bw.Write((uint)0x00); // reserved // Write the file size. bw.Write((uint)br.BaseStream.Length); // Write the size of the file name. bw.Write((uint)fileNameLength); // Write the file name (Unicode encoded). bw.Write(fileNameBytes); // Write the file name terminator. This is two nulls in Unicode. bw.Write(new byte[] {0,0}); // Iterate through the file reading data and writing it to the outbuffer. byte[] data = new byte[64*1024]; int bytesRead = 1; while (bytesRead > 0) { bytesRead = br.Read(data, 0, data.Length); bw.Write(data, 0, bytesRead); } } } // This memorystream will hold the Base64 encoded InfoPath attachment. MemoryStream msOut = new MemoryStream(); using (BinaryReader br = new BinaryReader(new MemoryStream(ms.ToArray()))) { // Create a Base64 transform to do the encoding. ToBase64Transform tf = new ToBase64Transform(); byte[] data = new byte[tf.InputBlockSize]; byte[] outData = new byte[tf.OutputBlockSize]; int bytesRead = 1; while (bytesRead > 0) { bytesRead = br.Read(data, 0, data.Length); if (bytesRead == data.Length) tf.TransformBlock(data, 0, bytesRead, outData, 0); else outData = tf.TransformFinalBlock(data, 0, bytesRead); msOut.Write(outData, 0, outData.Length); } } msOut.Close(); return base64EncodedFile = Encoding.ASCII.GetString(msOut.ToArray()); } } } |
在 Visual Studio NET 2003 创建解码器类
1. | 右击 AttachmentEncoding 在 SolutionExplorer@@, 指向 添加 , 并然后单击 @ @ @ AddNewItem@@@ 。 |
2. | 单击 模板 窗格中 类 AddNewItem@@ @ 对话框中, 在 名称 框中, 键入 InfoPathAttachmentDecoder.cs , 然后单击 打开 。 |
3. | 用以下代码替换 InfoPathAttachmentDecoder.cs 文件中所有代码。
using System; using System.IO; using System.Text; namespace InfoPathAttachmentEncoding { /// <summary> /// Decodes a file attachment and saves it to a specified path. /// </summary> public class InfoPathAttachmentDecoder { private const int SP1Header_Size = 20; private const int FIXED_HEADER = 16; private int fileSize; private int attachmentNameLength; private string attachmentName; private byte[] decodedAttachment; /// <summary> /// Accepts the Base64 encoded string /// that is the attachment. /// </summary> public InfoPathAttachmentDecoder(string theBase64EncodedString) { byte [] theData = Convert.FromBase64String(theBase64EncodedString); using(MemoryStream ms = new MemoryStream(theData)) { BinaryReader theReader = new BinaryReader(ms); DecodeAttachment(theReader); } } private void DecodeAttachment(BinaryReader theReader) { //Position the reader to get the file size. byte[] headerData = new byte[FIXED_HEADER]; headerData = theReader.ReadBytes(headerData.Length); fileSize = (int)theReader.ReadUInt32(); attachmentNameLength = (int)theReader.ReadUInt32() * 2; byte[] fileNameBytes = theReader.ReadBytes(attachmentNameLength); //InfoPath uses UTF8 encoding. Encoding enc = Encoding.Unicode; attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2); decodedAttachment = theReader.ReadBytes(fileSize); } public void SaveAttachment(string saveLocation) { string fullFileName = saveLocation; if(!fullFileName.EndsWith(Path.DirectorySeparatorChar)) { fullFileName += Path.DirectorySeparatorChar; } fullFileName += attachmentName; if(File.Exists(fullFileName)) File.Delete(fullFileName); FileStream fs = new FileStream(fullFileName, FileMode.CreateNew); BinaryWriter bw = new BinaryWriter(fs); bw.Write(decodedAttachment); bw.Close(); fs.Close(); } public string Filename { get{ return attachmentName; } } public byte[] DecodedAttachment { get{ return decodedAttachment; } } } } |
向 InfoPath 表单添加文件附件控件和文本框控件
1. | 在 AttachmentEncoding InfoPath 表单模板, 设计任务 任务窗格中单击 控件 。 |
2. | 在 控件 任务窗格中 InfoPath 2003, 单击 插入控件 下 文件附件 。
在 控件 任务窗格中 InfoPath 2007年, 单击 文件和图片 文件附件 。 |
3. | 右击 文件附件 控件, 并单击 文件附件属性 。 |
4. | 文件附件属性 对话框中, 在 字段名 框中, 键入 theAttachmentField , 然后单击 确定 。 |
5. | 在 控件 任务窗格中 InfoPath 2003, 单击 文本框 下 插入控件 。
在 控件 任务窗格中 InfoPath 2007年, 单击 常用 下 文本框 。 |
6. | 右击 文本框 控件, 并单击 文本框属性 。 |
7. | 文本框属性 对话框中, 在 字段名 框中, 键入 theAttachmentName , 然后单击 确定 。 |
向 InfoPath 窗体添加一个附加按钮
1. | 在 控件 任务窗格中 InfoPath 2003, 单击 插入控件 下 按钮 。
在 控件 任务窗格中 InfoPath 2007年, 单击 常用 下 按钮 。 |
2. | 右击新 按钮 控件, 然后单击 属性按钮 。 |
3. | 按钮属性 对话框中, 在 标签 框中, 键入 附加 在 ID 中, 键入 btnAttach , 然后单击 编辑表单代码 。 |
4. | 将以下代码添加到 btnAttach_OnClick 方法。
//Get a reference to the attachment node. IXMLDOMNode theAttachmentNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField"); //Get a reference to the filename node. IXMLDOMNode fileNameNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentName"); //Get the text of the node. String fileName = fileNameNode.text; if(fileName.Length > 0) { //Encode the file and assign it to the attachment node. InfoPathAttachmentEncoding.Encoder myEncoder = new InfoPathAttachmentEncoding.Encoder(fileName); if(theAttachmentNode.attributes.getNamedItem("xsi:nil") != null) theAttachmentNode.attributes.removeNamedItem("xsi:nil"); theAttachmentNode.text = myEncoder.ToBase64String(); } |
将保存按钮添加到 InfoPath 表单
1. | 切换到 AttachmentEncoding InfoPath 表单模板。 |
2. | 在 控件 任务窗格中 InfoPath 2003, 单击 插入控件 下 按钮 。
在 控件 任务窗格中 InfoPath 2007年, 单击 常用 下 按钮 。 |
3. | 右击新 按钮 控件, 然后单击 属性按钮 。 |
4. | 按钮属性 对话框中, 在 标签 框中, 键入 保存 在 ID 中, 键入 btnSave , 然后单击 编辑表单代码 。 |
5. | 将以下代码添加到 btnSave _OnClick 方法。
//Get a reference to the attachment node. IXMLDOMNode n = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField"); //Get the text of the node. String theAttachment = n.text; if(theAttachment.Length > 0) { InfoPathAttachmentEncoding.Decoder myDecoder = new InfoPathAttachmentEncoding.Decoder(theAttachment); myDecoder.SaveAttachment(@"<Path to save the file>"); } 注意 对于该代码, 将 要保存文件 < 路径 > 替换其中要保存文件位置。 |
确保 InfoPath 表单模板是完全信任
InfoPath 表单模板之前您可以测试此表单, 必须完全信任。 可使用下列方法之一进行确保 InfoPath 表单模板是完全信任:
• | 使用 Microsoft NET Framework 1.1 配置实用程序要只对 VisualC # 代码授予完全信任权限。 |
• | 使用 RegForm 实用程序从 InfoPath 软件开发工具包 (SDK) 来使窗体完全信任的表单。 这为 VisualC # 代码授予完全信任权限。 |
• | 使用代码签名证书对表单模板文件 (.xsn) 数字签名。 当您使用代码签名证书来数字签名表单模板文件, 要信任表单打开表单时提示用户。 这使窗体完全信任。 因此, 完全信任权限授予 VisualC # 代码。 |
• | 使用从 InfoPath SDK IPFullTrust 宏来使窗体完全信任的表单。 IPFullTrust 宏自动以用于完全信任, InfoPath 项目设置清单文件 (.xsf) 和表单模板文件, 然后 IPFullTrust 宏自动注册该表单模板。
有关如何安装和使用宏, 请访问 Microsoft Developer Network (MSDN) Web 站点: http://msdn2.microsoft.com/en-us/library/aa202736(office.11).aspx (http://msdn2.microsoft.com/en-us/library/aa202736(office.11).aspx)
|
• | InfoPath 中使用外部自动化来调用 RegisterSolution 方法。 由于只为单个计算机注册注册表单, 通常此方法仅用于表单开发。 对于任何其他形式, 其他用户必须注册自己计算机上其他表单。 我们不建议此方法用于其他表单。发布窗体时建议以前方法之一。 |
因为此表单是在表单开发, 可使用上次方法。 要这样做, 找到 AttachmentEncoding InfoPath 表单模板, 然后按照下列步骤:
1. | 在 工具 菜单上, 单击 窗体选项 。 |
2. | 单击 安全 选项卡。 |
3. | 单击以清除 自动决定安全级别根据表单设计 (推荐) 复选框。
InfoPath 注意 能自动检测业务逻辑要求完全信任权限。 因此, 必须明确授予完全信任权限。 |
4. | 完全信任 , 单击, 然后单击 确定 。 |
5. | 关闭 AttachmentEncoding InfoPath 表单模板。 如果您被提示要保存更改, 请单击 是 。
注意 任务不关闭 Visual Studio NET 2003 项目。 |
6. | 在 Visual Studio NET 2003, 双击在 SolutionExplorer@@ Manifest.xsf 文件。 Manifest.xsf 文件打开。 |
7. | 在根节点, 找到 publishUrl 属性。 删除 publishUrl 属性和值 publishUrl 属性。 |
8. | 保存更改, 并关闭 Manifest.xsf 文件。 |
9. | 单击 开始 单击 运行 , 键入 notepad , 然后单击 确定 。 |
10. | 将以下代码添加到空文本文件。
oApp = WScript.CreateObject("InfoPath.ExternalApplication"); strAbsolutePath = "<project_folder_url>\\Manifest.xsf"; oApp.RegisterSolution(strAbsolutePath,"overwrite"); 注意 对于该代码, 将 < project_folder_url > 替换项目文件夹中的 Manifest.xsf 文件的路径。 记住要转义的 Manifest.xsf 文件路径。 必须使用两个反斜杠 (\) 替换所有单个斜杠 (\) 路径中。 |
11. | 计算机上保存 Manifest.xsf 文件作为 Register.js 文件。 |
12. | 以调用 RegisterSolution 方法, 双击与您创建 Register.js 文件。 |
测试表单
1. | AttachmentEncoding Visual Studio NET 2003 项目, 中单击 调试 菜单上 开始 。 这将启动 InfoPath 表单处于预览模式。 |
2. | 在 InfoPath 表单, 键入与要在文本框中, 附加文件的路径, 然后单击 选用 。
注意 双击 文件附件 控件验证该文件是正确编码。 |
3. | 单击 A0 > 保存 。 定位, " 保存 按钮添加到 InfoPath 窗体 " 部分中所提供路径。 |
4. | 若要结束测试, 请单击 关闭预览 。 |
参考
http://msdn2.microsoft.com/en-us/library/aa168351(office.11).aspx