InfoPath 2010 또는 InfoPath 2007에서 Visual C#을 사용하여 프로그래밍 방식으로 파일 첨부 파일을 인코딩하고 디코딩하는 방법
요약
Microsoft InfoPath 2010 또는 Microsoft Office InfoPath 2007에서 파일 첨부 파일 컨트롤을 사용하여 InfoPath 양식 서식 파일에 파일을 첨부할 수 있습니다. 특정 상황에서는 파일 첨부 파일 컨트롤에 연결된 파일을 인코딩한 다음 디코딩할 수 있습니다. 이 경우 Microsoft Visual C#을 사용하여 인코더 클래스 및 Decoderclass를 만들 수 있습니다. 그런 다음, 인코더 클래스와 Decoderclass를 사용하여 파일 첨부 파일을 인코딩하고 디코딩할 수 있습니다. 이 문서에서는 양식에 첨부할 파일을 인코딩하고 파일 시스템에 저장하기 위해 첨부 파일을 디코딩하는 InfoPath 양식 서식 파일을 디자인하는 방법을 설명합니다.
InfoPath 2003에서 이 작업을 수행하는 방법에 대한 자세한 내용은 다음 문서 번호를 클릭하여 Microsoft 기술 자료의 문서를 봅니다.
892730 InfoPath에서 Visual C#을 사용하여 프로그래밍 방식으로 파일 첨부 파일을 인코딩 및 디코딩하는 방법
추가 정보
Microsoft는 특정 목적에 대한 상업성 및/또는 적합성에 대한 암시적 보증을 포함하되 이에 국한되지 않는 명시적 또는 묵시적 보증 없이 실례에 대한 프로그래밍 예제를 제공합니다. 이 문서의 내용은 프로시저를 작성하고 디버깅하는 데 사용되는 도구 및 여기에서 설명하는 프로그래밍 언어에 익숙한 사용자를 대상으로 합니다. Microsoft 지원 엔지니어는 사용자에게 도움이 되도록 특정 프로시저에 대한 기능을 설명할 수 있지만 사용자의 특정 요구 사항에 맞도록 예제를 수정하여 추가 기능을 제공하거나 프로시저를 구성하지는 않습니다.
다음 예제에서는 다음 단계를 수행합니다.
- Visual C# 프로젝트를 포함하는 양식을 만듭니다.
- 인코더 클래스를 만듭니다.
- Decoderclass를 만듭니다.
- 코드를 호출하도록 양식을 수정합니다.
- 양식에서 코드 작업을 테스트합니다.
Visual C# 프로젝트를 포함하는 양식 만들기
사용 중인 InfoPath 버전에 대한 지침을 사용하여 양식 서식 파일 및 프로젝트를 만듭니다.
InfoPath 2010
- InfoPath 디자이너에서 빈 양식 서식 파일을 만든 다음 저장 아이콘을 클릭합니다.
- 메시지가 표시되면 파일 이름을 입력하고 저장을 클릭합니다.
- **개발자 **탭을 클릭한 다음 언어를 클릭합니다.
- 양식 서식 파일 코드 언어에서 C#을 선택한 다음 확인을 클릭합니다.
InfoPath 2007
- **파일 **메뉴에서 양식 서식 파일 디자인을 클릭합니다.
- **양식 서식 파일 디자인 **작업창에서 공백 을 클릭한 다음 확인을 클릭합니다.
- 파일 메뉴에서 저장을 클릭합니다.
- 메시지가 표시되면 파일 이름 InfoPathAttachmentEncoding을 입력하고 저장을 클릭합니다.
- 도구 메뉴에서 양식 옵션을 클릭합니다.
- **양식 옵션 **대화 상자의 범주 아래에서 프로그래밍을 클릭합니다.
- 프로그래밍 언어 아래의 양식 서식 파일 코드 언어 목록에서 C#을 선택한 다음 확인을 클릭합니다.
인코더 클래스 만들기
사용 중인 InfoPath 버전에 대한 지침을 사용하여 인코더 클래스를 만듭니다.
InfoPath 2010
- 개발자 탭에서 **코드 편집기 **를 클릭하여 VSTA(Visual Studio Tools for Applications) 편집기를 시작합니다.
- 프로젝트 메뉴에서 새 항목 추가를 클릭합니다.
- 클래스를 선택하려면 클릭합니다.
- 이름 필드에서 이름을 InfoPathAttachmentEncoder.cs로 변경한 다음 저장을 클릭합니다.
- 코드 창에서 기존 코드를 다음 "인코더 코드" 섹션의 코드로 바꿉니다.
InfoPath 2007
- VSTA(Visual Studio Tools for Applications) 편집기를 시작합니다.
- **프로젝트 탐색기 **창에서 InfoPathAttachmentEncoding을 마우스 오른쪽 단추로 클릭하고 추가를 클릭한 다음 새 항목을 클릭합니다.
- 템플릿 섹션에서 클래스를 선택하고 이름을 InfoPathAttachmentEncoder.cs로 변경한 다음 추가를 클릭합니다.
- 코드 창에서 다음 "인코더 코드" 섹션의 코드를 붙여넣습니다.
인코더 코드
InfoPath 2010 또는 InfoPath 2007에서 다음 코드를 사용합니다.
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using InfoPathAttachmentEncoding;
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();
// Obtain 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());
}
}
}
Decoder 클래스 만들기
사용 중인 InfoPath 버전에 대한 지침을 사용하여 Decoderclass를 만듭니다.
InfoPath 2010
- 코드 편집기에서 프로젝트 메뉴에서 새 항목 추가를 클릭한 다음 클릭하여 클래스를 선택합니다.
- 이름 필드에서 이름을 InfoPathAttachmentDecoder.cs로 변경한 다음 저장을 클릭합니다.
- 코드 창에서 기존 코드를 다음 "디코더 코드" 섹션의 코드로 바꿉니다.
InfoPath 2007
- VSTA의 **프로젝트 탐색기 **창에서 InfoPathAttachmentEncoding을 마우스 오른쪽 단추로 클릭하고 추가를 클릭한 다음 새 항목을 클릭합니다.
- 템플릿 섹션에서 클래스를 선택하고 이름을 InfoPathAttachmentDecoder.cs로 변경한 다음 추가를 클릭합니다.
- 코드 창에서 다음 "디코더 코드" 섹션의 코드를 붙여넣습니다.
코드 디코더
InfoPath 2010 또는 InfoPath 2007에서 다음 코드를 사용합니다.
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 obtain 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.ToString())){
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 양식에 파일 첨부 파일 컨트롤, 텍스트 상자 컨트롤 및 단추 컨트롤을 추가합니다. 이렇게 하려면 다음과 같이 하십시오.
사용 중인 InfoPath 버전에 대한 지침을 사용하여 컨트롤 작업창을 엽니다.
- InfoPath 2010:InfoPathAttachmentEncoding InfoPath 양식 서식 파일의 **홈 **탭 아래에서 **컨트롤 **갤러리를 확장합니다.
- InfoPath 2007:InfoPathAttachmentEncoding InfoPath 양식 서식 파일에서 **디자인 작업 **작업 창에서 컨트롤 을 클릭합니다.
사용 중인 InfoPath 버전에 대한 지침을 사용하여 InfoPath 양식에 파일 첨부 파일 컨트롤을 추가합니다.
- InfoPath 2010: 컨트롤 작업창의 개체 아래에서 파일 첨부 파일을 클릭합니다.
- InfoPath 2007: 컨트롤 작업창의 파일 및 그림에서 파일 첨부 파일을 클릭합니다.
**파일 첨부 파일 **컨트롤을 마우스 오른쪽 단추로 클릭한 다음 파일 첨부 파일 속성을 클릭합니다.
**파일 첨부 파일 속성 **대화 상자에서 **필드 이름 **상자에AttachmentFieldin을 입력하고 확인을 클릭합니다.
사용 중인 InfoPath 버전에 대한 지침을 사용하여 InfoPath 양식에 Text Box 컨트롤을 추가합니다.
- InfoPath 2010: 컨트롤 작업창의 입력에서 텍스트 상자를 클릭합니다.
- InfoPath 2007: 컨트롤 작업창의 표준 아래에서 텍스트 상자를 클릭합니다.
텍스트 상자 컨트롤을 마우스 오른쪽 단추로 클릭한 다음 텍스트 상자 속성을 클릭합니다.
**텍스트 상자 속성 **대화 상자의 **필드 이름 **상자에AttachmentName을 입력하고 확인을 클릭합니다.
사용 중인 InfoPath 버전에 대한 지침을 사용하여 InfoPath 양식에 연결 단추를 추가합니다.
- InfoPath 2010: 컨트롤 작업창의 개체 아래에서 단추를 클릭합니다.
- InfoPath 2007: 컨트롤 작업창의 표준 아래에서 단추를 클릭합니다.
새 단추 컨트롤을 마우스 오른쪽 단추로 클릭한 다음 단추 속성을 클릭합니다.
**단추 속성 **대화 상자에서 **레이블 **상자에 첨부를 입력하고 ID 상자에 btnAttach를 입력한 다음 양식 코드 편집을 클릭합니다.
코드 창의 맨 위로 이동한 다음, 다음 코드 줄을 추가합니다.
using InfoPathAttachmentEncoding;
"여기서 코드 작성"으로 돌아가서 다음 코드를 추가합니다.
//Create an XmlNamespaceManager XmlNamespaceManager ns = this.NamespaceManager; //Create an XPathNavigator object for the Main data source XPathNavigator xnMain = this.MainDataSource.CreateNavigator(); //Create an XPathNavigator object for the attachment node XPathNavigator xnAttNode = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns); //Create an XPathNavigator object for the filename node XPathNavigator xnFileName = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentName", ns); //Obtain the text of the filename node. string fileName = xnFileName.Value; if (fileName.Length > 0) { //Encode the file and assign it to the attachment node. InfoPathAttachmentEncoder myEncoder = new InfoPathAttachmentEncoder(fileName); //Check for the "xsi:nil" attribute on the file attachment node and remove it //before setting the value to attach the filerRemove the "nil" attribute if (xnAttNode.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance")) xnAttNode.DeleteSelf(); //Attach the file xnAttNode.SetValue(myEncoder.ToBase64String()); }
InfoPath 양식에 저장 단추 추가
InfoPathAttachmentEncoding 양식 서식 파일로 돌아갑니다.
사용 중인 InfoPath 버전에 대한 지침을 사용하여 저장 단추를 추가합니다.
- InfoPath 2010: 컨트롤 작업창의 개체 아래에서 단추를 클릭합니다.
- InfoPath 2007: 컨트롤 작업창의 표준 아래에서 단추를 클릭합니다.
새 단추 컨트롤을 마우스 오른쪽 단추로 클릭한 다음 단추 속성을 클릭합니다.
**단추 속성 **대화 상자에서 **레이블 **상자에 저장을 입력하고** ID **상자에 btnSave를 입력한 다음 양식 코드 편집을 클릭합니다.
다음 코드를 삽입합니다.
//Create an XmlNamespaceManager XmlNamespaceManager ns = this.NamespaceManager; //Create an XPathNavigator object for the Main data source XPathNavigator xnMain = this.MainDataSource.CreateNavigator(); //Create an XPathNavigator object for the attachment node XPathNavigator xnAttNode = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns); //Obtain the text of the node. string theAttachment = xnAttNode.Value; if(theAttachment.Length > 0) { InfoPathAttachmentDecoder myDecoder = new InfoPathAttachmentDecoder(theAttachment); myDecoder.SaveAttachment(@"Path to the folder to save the attachment"); }
참고
이 코드에서 첨부 파일을 저장할 폴더의 자리 표시자 경로는 파일을 저장할 위치를 나타냅니다.
저장 아이콘을 클릭한 다음 VSTA를 닫습니다.
양식 테스트
이 양식에서 파일을 첨부하려면 InfoPath 양식 서식 파일을 완전히 신뢰할 수 있어야 합니다. 이를 확인하려면 다음 작업 중 하나를 수행합니다.
- 코드 서명 인증서를 사용하여 양식 서식 파일(.xsn)에 디지털 서명합니다. 이렇게 하면 양식을 열 때 양식을 신뢰하라는 메시지가 사용자에게 표시됩니다. 이렇게 하면 폼을 완전히 신뢰할 수 있습니다. 따라서 Visual C# 코드에 완전 신뢰 권한이 부여됩니다.
- 설치 가능한 템플릿을 만듭니다.
양식 서식 파일이 완전히 신뢰할 수 있는지 확인한 후 테스트해야 합니다. 이렇게 하려면 다음과 같이 하십시오.
사용 중인 InfoPath 버전에 대한 단계에 따라 미리 보기 모드에서 양식을 엽니다.
- InfoPath 2010 홈 탭에서 미리 보기를 클릭합니다.
- InfoPath 2007 Standardtoolbar에서 미리 보기를 클릭합니다.
InfoPath 양식에서 텍스트 상자에 첨부할 파일의 경로를 입력한 다음 첨부를 클릭합니다.
참고 파일 첨부 파일 컨트롤을 두 번 클릭하여 파일이 올바르게 인코딩되었는지 확인합니다.
저장을 클릭합니다.
"InfoPath 양식에 저장 단추 추가" 섹션의 코드에서 제공한 경로를 찾은 다음 파일이 해당 폴더에 저장되었는지 확인합니다.
미리 보기 닫기를 클릭합니다. 그러면 테스트가 종료됩니다.