Ask a questionAsk a question
 

QuestionUploading Files with Info Path Form

  • Monday, April 23, 2007 12:46 PMFHofmann77 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi,

     

    we'd like to provide an Info Path Forms Services based form to give users an easy web based ability to upload new documents with some metada and doeing some plausability tests to check if the metadata do make sense. The form will be presented to external users to provide documents in a structured and qualified way.

     

    So we created the InfoPath form and added a repeating "File-Attachment" control to the form. But with this control the files are attached to the InfoPath form itself and not uploaded to a document library. And so the internal users can not easyly work with the documents.

     

    So what would options do we have to customize InfoPath to provide an possiblility to upload documents to a document library?

     

    Frank

     

All Replies

  • Monday, April 23, 2007 6:05 PMAlexander Ekzarov Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Well, we had the same problem. I think solution for this situation is create .aspx page, wich will contain XmlFormView control with your Infopath form and your .Net user control (for example Upload control) wich will be responcible for uploading logic ....
  • Tuesday, May 29, 2007 7:51 AMdarryl29 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi,

     

    Can you please show me how it is done with the aspx page it will be extremely helpful. Thank you kindly for your help

     

    darryl29

  • Wednesday, May 30, 2007 12:16 AMGeorge Olson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hello,

     

    Glad to see someone else is trying this as well.  What you need to do is add an attribute to the form tag of master page that the aspx page is using.  On the master page add this attribute to the form tag:

    enctype="multipart/form-data"

     

    More info can be found on Nishand's Blog. http://blogs.gotdotnet.com/nishand/default.aspx

  • Wednesday, May 30, 2007 12:19 PMDavid Dean Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Another approach would be to allow InfoPath to capture the file attachments, then submit the form to a web service that programmatically extracts the files from the form template and posts them to the appropriate document library.

     

    The InfoPath Team Blog has a post with information on how to use the file attachment control:

     

    http://blogs.msdn.com/infopath/archive/2004/03/18/92221.aspx

     

    I've found through experience that storing large attachments within the form XML is pretty slow, but it should be OK for handling an upload as long as you include code to remove the attachment instances from the form XML before you save the XML document - possibly by using a separate element to store the URL of the saved document.

  • Wednesday, May 30, 2007 3:05 PMGeorge Olson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi David,

    Good point, I should have clarified that this was what I was talking about.  However there are two implications.  The first is if you are using the XmlFormView control on a page and you need to set the attribute or else there will be an error saying that the file cannot be found.  If you check the logs it will say something about pascal session state and that someone is trying to hack your site.  The second is that files attached in InfoPath, at least 2007, are encoded in a special format and in base 64.  I have combined what I have found.  If you can make it better please do and post your suggestions.

     

    Code Snippet

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    using System.IO;

     

    namespace CTED.InfoPath

    {

        /// <summary>

        /// Class used to decode an InfoPath attachment.

        /// Pulls the file name and the decoded file from either a base 64 byte array or string.

        /// </summary>

        public class InfoPathAttachmentDecoder

        {

            //  Private string to hold the attachment name.

            string _fileName;

     

            //  Private byte array to hold the decoded attachment.

            byte[] _decodedFile;

     

            /// <summary>

            /// The name of the file within the InfoPath attachment.

            /// </summary>

            public string Filename

            {

                get { return _fileName; }

            }

     

            /// <summary>

            /// The decoded file within the InfoPath attachment.

            /// </summary>

            public byte[] DecodedFile

            {

                get { return _decodedFile; }

            }

     

            /// <summary>

            /// Constructor for the InfoPathAttachmentDecoder Class

            /// </summary>

            /// <param name="base64EncodedString">The attachment represented by a string</param>

            public InfoPathAttachmentDecoder(string base64EncodedString)

            {

                //  Use unicode encoding.

                Encoding _encoding = Encoding.Unicode;

     

                //  The byte array containing the data.

                byte[] _data = Convert.FromBase64String(base64EncodedString);

     

                //  Use a memory stream to access the data.

                using (MemoryStream _memoryStream = new MemoryStream(_data))

                {

                    //  Create a binary reader from the stream.

                    BinaryReader _theReader = new BinaryReader(_memoryStream);

     

                    //  Create a byte array to hold the header data.

                    byte[] _headerData = _theReader.ReadBytes(16);

     

                    //  Find the file size before finding the file name.

                    int _fileSize = (int)_theReader.ReadUInt32();

     

                    //  Get the file name.

                    int _attachmentNameLength = (int)_theReader.ReadUInt32() * 2;

                    byte[] _fileNameBytes = _theReader.ReadBytes(_attachmentNameLength);

                    _fileName = _encoding.GetString(_fileNameBytes, 0, _attachmentNameLength - 2);

     

                    //  Get the decoded attachment.           

                    _decodedFile = _theReader.ReadBytes(_fileSize);

                }

            }

           

            /// <summary>

            /// Constructor for the InfoPathAttachmentDecoder Class

            /// </summary>

            /// <param name="base64EncodedBytes">The attachment represented by a byte array</param>

            public InfoPathAttachmentDecoder(byte[] base64EncodedBytes) : this(Convert.ToBase64String(base64EncodedBytes)) { }

     

            /// <summary>

            /// Static method that gets the file from the attachment.

            /// </summary>

            /// <param name="base64EncodedString">The attachment represented by a string</param>

            /// <returns>Returns a byte array of the file in the attachment.</returns>

            public static byte[] DecodeInfoPathAttachment(string base64EncodedString)

            {

                //  Create an instance of the InfoPathAttachmentDecoder

                InfoPathAttachmentDecoder _infoPathAttachmentDecoder = new InfoPathAttachmentDecoder(base64EncodedString);

               

                //  Return the decoded file.

                return _infoPathAttachmentDecoder.DecodedFile;

            }

     

            /// <summary>

            /// Static method that gets the file from the attachment.

            /// </summary>

            /// <param name="base64EncodedBytes">The attachment represented by a byte array</param>

            /// <returns>Returns a byte array of the file in the attachment.</returns>

            public static byte[] DecodeInfoPathAttachment(byte[] base64EncodedBytes)

            {

                //  Create an instance of the InfoPathAttachmentDecoder

                InfoPathAttachmentDecoder _infoPathAttachmentDecoder = new InfoPathAttachmentDecoder(base64EncodedBytes);

               

                //  Return the decoded file.

                return _infoPathAttachmentDecoder.DecodedFile;

            }

     

     

  • Wednesday, May 30, 2007 3:27 PMGeorge Olson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Here is another option, but can someone explain why it doesn't need to be converted from base64?

     

    Code Snippet

    /// <summary>

    /// Constructor for the InfoPathAttachmentDecoder Class

    /// </summary>

    /// <param name="base64EncodedBytes">The attachment represented by a byte array</param>

    public InfoPathAttachmentDecoder(byte[] base64EncodedBytes)

    {

    // Position 20 contains a DWORD indicating the length of the

    // filename buffer. The filename is stored as Unicode so the

    // length is multiplied by 2.

    int _fnLength = base64EncodedBytes[20] * 2;

    // Create bytes for the file.

    byte[] _fnBytes = new byte[_fnLength];

    // The actual filename starts at position 24 . . .

    for (int _index = 0; _index < _fnLength; _index++)

    {

    _fnBytes[_index] = base64EncodedBytes[24 + _index];

    }

    // Convert the filename bytes to a string. The string

    // terminates with \0 so the actual filename is the

    // original filename minus the last character !

    char[] _charFileName = System.Text.UnicodeEncoding.Unicode.GetChars(_fnBytes);

    _fileName = new string(_charFileName);

    _fileName = _fileName.Substring(0, _fileName.Length - 1);

    // The file is located after the header, which is 24 bytes long

    // plus the length of the filename.

    _decodedFile = new byte[base64EncodedBytes.Length - (24 + _fnLength)];

    // Add the bytes to the file.

    for (int _index = 0; _index < _decodedFile.Length; ++_index)

    {

    _decodedFile[_index] = base64EncodedBytes[24 + _fnLength + _index];

    }

    }

     

  • Wednesday, July 11, 2007 9:24 PMAndré Rentes Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi,

     

    I used these class above and saved file name and decode file in database.

     

    Now I have a another infopath form and I 'd like that when it to load I need "SetValue" to File Attachment control.

     

    It`s possible?

     

      I'd like to load  this form with a attched file(decode file) in my control!
     
      Thanks!
  • Tuesday, June 03, 2008 1:33 PMSP_Pepe Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

     

    Hi,

     

    Is that all the code I need to upload the Attached file 64? I'd be greatly appreaciated if you could give me some instructions in detail.

     

    Thanks in advance.

  • Tuesday, March 31, 2009 10:41 AMRodolfo Cardoso Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks George, your class works perfectly to decode a file from a template, realy helpfull!
    Rodolfo Cardoso
  • Monday, September 28, 2009 1:23 PMgiangy11 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    can someone give me more detailed instructions to how and where implement this class?