SPS Searching of InfoPath file attachments - InfoPath Dev
in

InfoPath Dev

SPS Searching of InfoPath file attachments

Last post 05-31-2007 12:49 AM by darryl2912. 9 replies.
Page 1 of 1 (10 items)
Sort Posts: Previous Next
  • 11-08-2005 01:50 PM

    • rdcpro
    • Not Ranked
    • Joined on 11-08-2005
    • USA
    • Posts 6

    SPS Searching of InfoPath file attachments

    It doesn't seem like SharePoint can crawl/search the content of an InfoPath file attachment, at least not out of the box. This seems strange to me, since that would be a fairly common scenario for InfoPath/SharePoint integration with attachments. So, maybe I'm overlooking something.

    Does anyone know of a way to get SharePoint to crawl a file attachment in an InfoPath form that doesn't involve programmatically extracting the encoded binary from the form and saving it separately to a doc lib? Hopefully there is an "out of the box" solution I'm overlooking, or else a widget that we could buy for this.

    Otherwise I'll write the code to do it, and plug it into an existing web service...

    Thanks in advance,
    Mike
  • 11-08-2005 02:25 PM In reply to

    Re: SPS Searching of InfoPath file attachments

    Do you mean an IP file attachment in an IP xml file?

    Those are stored in base64 encoding, so i see no obvious way to index them, especially because IP add a special header to them (containing filename, icon etc) that you need to remove programmaticly to access the file outside IP.

    //AndersR


  • 11-08-2005 02:34 PM In reply to

    • rdcpro
    • Not Ranked
    • Joined on 11-08-2005
    • USA
    • Posts 6

    Re: SPS Searching of InfoPath file attachments

    Yes, that's what I was referring to. It seems pretty limiting to have InfoPath forms with attachments that can't be indexed.

    I know that I can do it programmatically, and of course I'll have to read the header structure as well to get the filename, among other things. But I was hoping there was something simpler I was overlooking.

    Regards,
    Mike Sharp
  • 11-09-2005 12:34 AM In reply to

    Re: SPS Searching of InfoPath file attachments

    SPS can do this. You have to do some special stuff to make it happen but it is doable. We have a solution that uses search. However, we also chose to provide an InfoPath form that searches the form library since we had more control over it. SPS search wasn't configurable enough for our solution requirements.

    Attachments is a bigger issue. Don't know if this is going to be handled or not in the next version.

    Patrick Halstead [InfoPath MVP]
    InfoPathDev
    Patrick Halstead
    Project Manager at Qdabra
  • 11-09-2005 10:11 AM In reply to

    • rdcpro
    • Not Ranked
    • Joined on 11-08-2005
    • USA
    • Posts 6

    Re: SPS Searching of InfoPath file attachments

    Oh, I'd say if you're willing to write code to work with SharePoint's query service, its quite configurable, especially if you write an IFilter for any special stuff (such as custom metadata).

    But yes, attachments are the issue for me. I can search the InfoPath form just fine.

    I guess I'll modify my FormSubmitService to extract the attachment, and PUT it to a separate SharePoint document library.

    Thanks!

    Regards,
    Mike Sharp
  • 11-09-2005 02:05 PM In reply to

    Re: SPS Searching of InfoPath file attachments

    Let me know if you run into trouble extracting the attachments and adding them to SPS.

    I already did this, and you need to tweak both IP and SPS a bit to make it happen:

    -no web service makes you add images with meta data, so if meta data is an issue you need either to create a custom SPS web service or use FP-Remote Procedure Calls. If no meta data is needed, the Upload method of Imaging.asmx is your friend. Creating a custom web service for sharepoint is straight forward thoughhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_SP2003_ta/html/ODC_WritingCustomWebServicesforSPPT.asp
    -extracting the headers takes some effort. Matthew Blain (co-writer of Mr Halstead's book "Developing solutions with MS InfoPath") created some code that does this. The pages with his InfoPath tips are down at the moment, but you can grab them using the WayBackMachine:http://web.archive.org/web/20041009132349/http://tips.serriform.com/CSharpCreateInfoPathAttachment.htm

    hth
    //AndersR


  • 11-09-2005 04:33 PM In reply to

    • rdcpro
    • Not Ranked
    • Joined on 11-08-2005
    • USA
    • Posts 6

    Re: SPS Searching of InfoPath file attachments

    Thanks Anders,

    Even though Matthew is creating the InfoPath header (and I want to extract it), that example will save me quite a bit of time. I figured out the header structure from the documentation, but there were a few parts that weren't completely clear (e.g., it mentioned I needed a non-ASCII character, but didn't say it should be a null!). And I hadn't noticed that the filename length was in characters, not bytes...I probably would have wasted some time before I figured that out! ;^)

    I can't help thinking that what would really be useful here is a new InfoPath IFilter...I've had great success with a custom HTML IFilter I use to index our content management system. In that case, I wouldn't have to mess with the attachment in the InfoPath form at all, and I could deal with any IP form posted to SharePoint, not just those that are processed with my web service. But, it's probably less work to modify my web service to strip the attachment anyway.

    Thanks again,
    Mike Sharp
  • 11-10-2005 12:15 AM In reply to

    Re: SPS Searching of InfoPath file attachments

    At the end if the post i have pasted my version of the code from Matthews and Patricks book (basicly i translated the VB from the book to C# using a reflector). Some conversions were made, for example i use a class not a struct because of null handling.

    You use it like this:

    InfoPathAttachment attachment = new InfoPathAttachment();
    try
    {
    //remove binary InfoPath header
    attachment = InfoPathAttachment.DecodeAttachment(document.text);
    }
    catch (Exception e)
    {
    System.Diagnostics.Debug.WriteLine(e);
    throw new Exception("UploadDocument: InfoPath attachment decoding error: " + e);
    }
    byte[] bytes = attachment.FileData;
    string fileName = attachment.FileName.Substring(0, attachment.FileName.Length - 1);//remove terminating zero

    Then its just a matter of calling your imaging or custom web service.

    Remember when you recieve the infopath attachment filename, that it is has a terminating zero, so you need to remove the last char to make your web service call well-formed.

    have fun!
    //AndersR

    P.S a shame your first name isnt Carl or something! C Sharp would be the coolest coding name ever :-D

    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;



    namespace Creuna.InfoPath
    {
    public class InfoPathAttachment
    {
    // Fields
    public byte[] FileData;
    public string FileName;

    /// <summary>
    /// .NET representation of the InfoPath File Attachment Header
    /// </summary>
    [ StructLayout(LayoutKind.Sequential, Pack=1) ]
    private class AttachmentStructure
    {
    public int Signature;
    public int HeaderSize;
    public int InfopathVersion;
    public int Reserved;
    public int Filesize;
    public int FilenameCharLen;
    }

    /// <summary>
    /// converts a byte array to an AttachmentStructure
    /// </summary>
    /// <param name="attachmentArray"></param>
    /// <returns>AttachmentStructure</returns>
    private static AttachmentStructure BytesToHeaderStructure( byte[] attachmentArray )
    {
    int structureLength = Marshal.SizeOf(typeof(InfoPathAttachment.AttachmentStructure));

    if (attachmentArray.Length < structureLength)
    return null;

    //Allocates memory from the unmanaged memory
    IntPtr pointer = Marshal.AllocHGlobal(structureLength);

    //Copy data from a one-dimensional, managed 8-bit unsigned integer array to an unmanaged memory pointer
    Marshal.Copy(attachmentArray, 0, pointer, structureLength);

    //Marshal data from an unmanaged block of memory to a managed object
    AttachmentStructure attachmentStructure = (AttachmentStructure) Marshal.PtrToStructure(pointer, typeof(AttachmentStructure));
    Marshal.FreeHGlobal(pointer);
    return attachmentStructure;
    }


    public static int Base64EncodedLength(int cb)
    {
    //The base64 encoded header will always be 4/3 the size of the
    //binary version, rounded up to a multiple of 4.
    return (int) Math.Round((double) (Math.Ceiling(((double) cb) / 3) * 4));
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="InnerTextAttachment"></param>
    /// <returns></returns>
    public static InfoPathAttachment DecodeAttachment(string InnerTextAttachment)
    {
    AttachmentStructure attachmentStructure = new AttachmentStructure();
    InfoPathAttachment infoPathAttachment = new InfoPathAttachment();

    //get encoded length of header
    int cbHeaderEncoded = InfoPathAttachment.Base64EncodedLength(Marshal.SizeOf(attachmentStructure.GetType()));
    if ( InnerTextAttachment.Length < cbHeaderEncoded )
    {
    throw new Exception("Encoded string is not long enough to include header.");
    }

    //decode header from string to byte
    byte[] rgHeader = Convert.FromBase64String(InnerTextAttachment.Substring(0, cbHeaderEncoded));

    //decode header from bytes to structure
    attachmentStructure = InfoPathAttachment.BytesToHeaderStructure(rgHeader);

    //check the signature
    //1095125447 dec is 0x414649c7 hex, or {199, 73, 70, 65}.
    if (!attachmentStructure.Signature.Equals(0x414649c7))
    {
    throw new Exception("Signature does not match InfoPath attachment signature.");
    }

    //Check the header size.
    //The size of the header does not include the size of the signature.
    int headerSizeRequired = Marshal.SizeOf(attachmentStructure.GetType()) - 4;
    if (!attachmentStructure.HeaderSize.Equals(headerSizeRequired))
    {
    throw new Exception("Header size does not match expected size.");
    }

    //Check body
    int cbBodyEncoded = InfoPathAttachment.Base64EncodedLength((attachmentStructure.FilenameCharLen * 2) + attachmentStructure.Filesize);
    if (InnerTextAttachment.Length < (cbHeaderEncoded + cbBodyEncoded))
    {
    throw new Exception("Encoded string is not long enough to include body.");
    }


    byte[] rgBody = Convert.FromBase64String(InnerTextAttachment.Substring(cbHeaderEncoded, cbBodyEncoded));

    //copy out filename
    infoPathAttachment.FileName = Encoding.Unicode.GetString(rgBody, 0, attachmentStructure.FilenameCharLen * 2);

    //copy out the rest of the file bytes
    infoPathAttachment.FileData = (byte[]) Array.CreateInstance(typeof(byte), attachmentStructure.Filesize);
    Array.Copy(rgBody, (int) (attachmentStructure.FilenameCharLen * 2), infoPathAttachment.FileData, 0, attachmentStructure.Filesize);

    return infoPathAttachment;
    }


    }


    }
  • 05-31-2007 12:36 AM In reply to

    Re: SPS Searching of InfoPath file attachments

    Hi AndersonR

    How do you use this code?

    I am in Sharepoint 2007 and I want to extract the InfoPath File Attachment out of a form Library and then place that attachment that I extracted into a Custom List. How would you do this using your code? A web part or a feature. I am not sure?

     

    Please help.

    Kind Regards

    darryl2912

  • 05-31-2007 12:49 AM In reply to

    Re: SPS Searching of InfoPath file attachments

    Hi rdcpro,

     

    Can you help me by using your FormSubmitService to be able to submit the file attachment attached to a IP form and place it into a SharePoint 2007 List?

     

    Please Help

    Kind Regards

    darryl2912

Page 1 of 1 (10 items)
Copyright © 2003-2019 Qdabra Software. All rights reserved.
View our Terms of Use.