Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading file from Flex to WCF REST Stream issues (how to decode multipart form post in REST WS)

The system is a Flex application communicating with a WCF REST web service. I am trying to upload a file from the Flex application to the server and am running into some issues I'm hoping someone here will be able to help out with. I'm using a FileReference in the Flex app to browse and upload the file as defined here:

http://blog.flexexamples.com/2007/09/21/uploading-files-in-flex-using-the-filereference-class/

I am then receiving the file as a Stream (shows as System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream in the debugger) in the WCF REST web service (using project type of WCF 4 REST Service)

[WebInvoke(Method = "POST", UriTemplate = "_test/upload")]
public void UploadImage(Stream data)
{
    // TODO: just hardcode filename for now
    var filepath = HttpContext.Current.Server.MapPath(@"~\_test\testfile.txt");
    using (Stream file = File.OpenWrite(filepath))
    {
        CopyStream(data, file);
    }
}
private static void CopyStream(Stream input, Stream output)
{
    var buffer = new byte[8 * 1024];
    int len;
    while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }
}

Note: CopyStream method used from this post: How do I save a stream to a file in C#?

The file saves without any issues. The issue I have is that the file contains more information than i would like. Here are the contents of the saved file (where the source file only contained "THIS IS THE CONTENT OF THE FILE"):

------------ae0ae0Ef1ae0Ef1ae0gL6gL6Ij5cH2
Content-Disposition: form-data; name="Filename"

testfile.txt
------------ae0ae0Ef1ae0Ef1ae0gL6gL6Ij5cH2
Content-Disposition: form-data; name="Filedata"; filename="testfile.txt"
Content-Type: application/octet-stream

THIS IS THE CONTENT OF THE FILE
------------ae0ae0Ef1ae0Ef1ae0gL6gL6Ij5cH2
Content-Disposition: form-data; name="Upload"

Submit Query
------------ae0ae0Ef1ae0Ef1ae0gL6gL6Ij5cH2--

The contents look exactly like they are described in the Adobe documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html

Are there any facilities in C# to get the file contents from the Stream?

EDIT (3/24 8:15 pm): What the Flex app is sending is a Multipart form POST. How can I decode the multipart body data as represented by the Stream parameter and strip out the pieces of the multipart body?

EDIT (3/25 10 am): some more Stack Overflow posts that are related:
WCF service to accept a post encoded multipart/form-data
POSTing multipart/form-data to a WCF REST service: the action changes

EDIT (3/25 10:45 am): Found a multipart parser that works very well:
http://antscode.blogspot.com/2009/11/parsing-multipart-form-data-in-wcf.html

Thanks in advance.

like image 586
Ed Sinek Avatar asked Mar 24 '11 17:03

Ed Sinek


1 Answers

I open-sourced a C# Http form parser here.

This is slightly more flexible than the other one mentioned which is on CodePlex, since you can use it for both Multipart and non-Multipart form-data, and also it gives you other form parameters formatted in a Dictionary object.

This can be used as follows:

non-multipart

public void Login(Stream stream)
{
    string username = null;
    string password = null;

    HttpContentParser parser = new HttpContentParser(data);
    if (parser.Success)
    {
        username = HttpUtility.UrlDecode(parser.Parameters["username"]);
        password = HttpUtility.UrlDecode(parser.Parameters["password"]);
    }
}

multipart

public void Upload(Stream stream)
{
    HttpMultipartParser parser = new HttpMultipartParser(data, "image");

    if (parser.Success)
    {
        string user = HttpUtility.UrlDecode(parser.Parameters["user"]);
        string title = HttpUtility.UrlDecode(parser.Parameters["title"]);

        // Save the file somewhere
        File.WriteAllBytes(FILE_PATH + title + FILE_EXT, parser.FileContents);
    }
}
like image 143
Lorenzo Polidori Avatar answered Oct 26 '22 14:10

Lorenzo Polidori