如何进行编码和解码通过使用 C# 在 InfoPath 2003 中以编程方式的文件附件

文章翻译 文章翻译
文章编号: 892730 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

在 InfoPath 2007 中 Microsoft Office 或 Microsoft Office InfoPath 2003 Service Pack 1 (SP1) 中,您可以使用 文件附件 要将文件附加到 InfoPath 表单模板控件。在特定情况下,您可能希望进行编码,然后解码附加到文件 文件附件 控件。在这种情况下,您可以使用 Microsoft Visual C# 创建 编码器 类和 解码器 类。然后,您可以使用 编码器 类和 解码器 要进行编码和解码该文件的类附件。

简介

本文介绍如何进行编码和解码通过使用 Microsoft Visual C# 在 InfoPath 2003 中以编程方式的文件附件。有关如何执行此操作,InfoPath 2010 年或在 InfoPath 2007 中的信息,请参见以下 web 页: 如何进行编码和解码通过使用 C# InfoPath 2010 年或在 InfoPath 2007 中以编程方式的文件附件.

更多信息

Microsoft 提供的编程示例仅用于说明,没有任何明示或暗示的担保。这包括但不限于对适销性或特定的适用性的暗示保证目的。本文假定您熟悉编程演示语言以及用于创建工具和调试过程。Microsoft 的支持工程师可以帮助解释某个特定的过程的功能,但他们不会修改这些示例以提供附加的功能或构建过程以满足您具体的要求。

创建可视 C# InfoPath 2003 项目

  1. 启动 Microsoft Visual Studio。NET 2003。
  2. 在上 文件 菜单上,单击然后单击 项目.
  3. 在中 新项目 对话框中,单击Visual C# 项目 Microsoft Office InfoPath 项目中文件夹。
  4. 在中 名称 框中键入AttachmentEncoding然后单击确定.
  5. 在 Microsoft Office 项目向导中,单击创建新的表单模板然后单击完成.

    Microsoft Office 项目向导创建新的 Visual Studio。NET 2003 中名为 AttachmentEncoding 的项目。一个此外会创建 InfoPath 表单模板。InfoPath 表单模板是名为 AttachmentEncoding。

在 Visual Studio 中创建一个编码的类。NET 2003

  1. 在解决方案资源管理器中,用鼠标右键单击AttachmentEncoding指向 添加然后单击 添加新项.
  2. 在中 添加新项 对话框中,单击 在中 模板 窗格中类型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指向 添加然后单击 添加新项.
  2. 在中 添加新项 对话框中,单击 在中 模板 窗格中类型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. 在中 控件任务窗格中单击文件附件 在下插入控件.
  3. 用鼠标右键单击 文件附件 控件,然后单击 文件附件属性.
  4. 在中 文件附件属性 对话框框中键入 theAttachmentField 在中 字段名称 框中,然后单击 确定.
  5. 在中 控件任务窗格中单击文本框 在下插入控件.
  6. 用鼠标右键单击 文本框 控件,然后单击 文本框属性.
  7. 在中 文本框属性 对话框中,类型 theAttachmentName 在中 字段名称 框中,然后单击 确定.

InfoPath 窗体中添加一个附加按钮

  1. 在中 控件任务窗格中单击按钮 在下插入控件.
  2. 用鼠标右键单击新 按钮 控件,和然后单击 按钮属性.
  3. 在中 按钮属性 对话框中键入附加 在中 标签 框中键入btnAttach 在中 ID 框中,然后单击编辑表单代码.
  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. 在中 控件任务窗格中单击按钮 在下插入控件.
  3. 用鼠标右键单击新 按钮 控件,和然后单击 按钮属性.
  4. 在中 按钮属性 对话框中键入保存 在中 标签 框中键入btnSave 在中 ID 框中,然后单击编辑表单代码.
  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>");
    }			
    
    注意 在此代码中,替换 <Path to="" save="" the="" file=""></Path> 您要保存的位置文件。

请确保 InfoPath 表单模板是完全受信任

之前,您可以测试该表单,InfoPath 表单模板必须是完全受信任的。您可以使用下列方法之一来确保InfoPath 表单模板不完全受信任:
  • 使用 Microsoft。NET Framework 1.1 配置实用程序授予完全信任权限仅 C# 代码。
  • 使用 RegForm 实用程序从 InfoPath 软件开发工具包 (SDK) 使表单完全受信任的表单。这将授予完全信任您的 C# 代码的权限。
  • 用于代码签名证书对表单进行数字签名模板文件 (.xsn)。当您使用代码签名证书进行数字签名表单模板文件中,信任该窗体在打开时提示用户窗体。这会使表单完全受信任。因此,都是完全信任权限授予您的 C# 代码。
  • 使用 IPFullTrust 从 InfoPath SDK,这将使表单完全受信任的宏窗体。" IPFullTrust 宏可以自动设置的清单文件 (.xsf) 和窗体有关完全信任,InfoPath 项目中的模板文件,然后 IPFullTrust 宏会自动注册表单模板。

    对于有关如何安装和使用宏,请访问以下详细信息Microsoft 开发人员网络 (MSDN) 的 Web 站点:
    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 中,双击Manifest.xsf 在解决方案资源管理器中的文件。Manifest.xsf 文件将打开。
  7. 在根节点,找到 异常 属性。删除 异常 属性和值 异常 属性。
  8. 保存所做的更改,并关闭 Manifest.xsf文件。
  9. 单击 启动单击 运行,类型 记事本然后单击确定.
  10. 将下面的代码添加到空白的文本文件中。
    oApp = WScript.CreateObject("InfoPath.ExternalApplication");
    strAbsolutePath = "<project_folder_url>\\Manifest.xsf";
    oApp.RegisterSolution(strAbsolutePath,"overwrite"); 
    
    注意 在此代码中,替换<project_folder_url></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. 单击 保存.定位路径,您提供在"添加 保存 InfoPath 表单按钮"一节。
  4. 若要结束测试,请单击 关闭预览.

参考

有关文件附件标头的详细信息设置格式,请访问下面的 MSDN 网站:
在 InfoPath 2003 中附加文件
http://msdn2.microsoft.com/en-us/library/aa168351 (office.11).aspx

属性

文章编号: 892730 - 最后修改: 2012年3月5日 - 修订: 0.1
这篇文章中的信息适用于:
  • Microsoft Office InfoPath 2003
关键字:?
kbcode kbscript kbsample kbxml kbprogramming kbhowto kbmt KB892730 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 892730
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com