概要
Microsoft Office InfoPath 2003 Service Pack 1 (SP 1), 或 Microsoft Office InfoPath 2007年中可使用 文件附件 控件将文件附加到 InfoPath 表单模板。 您可能希望在特定情况, 编码和解码文件附加到 文件附件 控件然后 这种在情况下, 您可以使用 MicrosoftVisualC # 来创建类 编码器 和 解码器 类。然后, 可用于 编码器 类和 解码器 类编码和解码文件附件。
INTRODUCTION
本文介绍如何编码和解码文件附件通过 MicrosoftVisualC # 编程。
更多信息
Microsoft 提供编程示例仅, 供图示不附带任何明示或暗示。 这包括, 但不仅限于, 适销性或用于特定目的适用性的暗示保证。本文假定您已熟悉与正在演示编程语言以及工具来调试过程来创建和使用。 Microsoft 支持工程师可以帮助解释功能的特定过程, 但它们将会修改这些示例以提供添加功能或构建过程以满足特定要求。
因为此表单是在表单开发, 可使用上次方法。 要这样做, 找到 AttachmentEncoding InfoPath 表单模板, 然后按照下列步骤:
创建 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 方法。 由于只为单个计算机注册注册表单, 通常此方法仅用于表单开发。 对于任何其他形式, 其他用户必须注册自己计算机上其他表单。 我们不建议此方法用于其他表单。发布窗体时建议以前方法之一。 |
| 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. | 若要结束测试, 请单击 关闭预览 。 |
参考
有关文件附件头格式, 请访问以下 MSDN 网站:
附加文件 InfoPath 2003
http://msdn2.microsoft.com/en-us/library/aa168351(office.11).aspx
http://msdn2.microsoft.com/en-us/library/aa168351(office.11).aspx

回到顶端
浙公网安备 33010602011771号