Asynchronous Multipart-form POST

780 views
Skip to first unread message

Kappel

unread,
Jun 12, 2012, 3:31:09 PM6/12/12
to rest...@googlegroups.com
First off, thank you to all who have contributed to RestSharp.  It has been extremely useful to me, and I have learned a lot by digging through it.  Thank you so much.

I am currently working on an application that needs to upload files to a RESTful service via a multipart-form POST.  RestSharp has several different ways to do this, but I ran into an issue when trying to report the upload progress of files (while executing the POST asynchronously, of course).  The only way I could see to report progress was to pass add the file(s) using the following overload of the RestRequest.AddFile method:

request.AddFile(string name, Action<Stream> writer, string fileName, string contentType)

From the UI thread, I would pass along a writer that would report progress during the file upload.  However, the POST fails every time because the content-length of the request isn't set correctly.  In looking through the RestRequest class, I found that the FileParameter.ContentLength is not unless you pass along a byte[] instead of an Action<Stream>.  And if I pass along a byte[] instead of a function, I can't report the progress of the upload.

My quick solution was to add the following overload to the RestRequest class:

        /// <summary>
        /// Adds the bytes to the Files collection with the specified file name and content type
        /// </summary>
        /// <param name="name">The parameter name to use in the request</param>
        /// <param name="writer">A function that writes directly to the stream.  Should NOT close the stream.</param>
        /// <param name="fileName">The file name to use for the uploaded file</param>
        /// <param name="contentType">The MIME type of the file to upload</param>
        /// <param name="contentLength">The size (in bytes) of the file to upload</param>
        /// <returns>This request</returns>
        public IRestRequest AddFile(string name, Action<Stream> writer, string fileName, string contentType, long contentLength)
        {
            return AddFile(new FileParameter { Name = name, Writer = writer, FileName = fileName, ContentType = contentType, ContentLength = contentLength });
        }

This provides the functionality I need.  I wanted to post this to the group to see if there was a better way to do this, or if this is something that would be helpful to others.

Don Park

unread,
Jul 13, 2012, 6:32:44 AM7/13/12
to rest...@googlegroups.com
I ran into the same problem but chose to enumerate `RestRequest.Files` to find the offending `FileParameter` and set its `ContentLength` to avoid overhead of maintaining my own version of RestSharp.

Andrew Young

unread,
Jul 13, 2012, 12:26:26 PM7/13/12
to rest...@googlegroups.com
That definitely sounds like a bug. We will need to modify the AddFile overload to take in the contentLength like Kappel said. It would seem appropriate, from what I know, to add that overload to IRestRequest. Unfortunately, this means that method signatures change signaling a major version bump to 104. I am ignorant of the history of why this overload wasn't exposed in the interface. Another admin can probably answer that more specifically. Maybe it just wasn't fully supported.

Is there a reason why you couldn't just send in a byte array?

Don Park

unread,
Jul 16, 2012, 12:23:14 AM7/16/12
to rest...@googlegroups.com
> Is there a reason why you couldn't just send in a byte array?

In my use-case, files being uploaded were huge and could not be loaded fully into memory.

'Content-Length' issue gets more complicated when data being uploaded is a true stream, meaning length of data is not available at the time of POST, only at the time of termination.

I would suggest just adding AddStream method to formally support Stream for now to cover most common use-cases. AddStream should set Content-Length to Stream.Length. If Stream.Length throws NotSupportedException then do not remove Content-Length header from request.

BTW, I created issue #297 before reading the READ BEFORE message. Please go ahead and close the issue if it's inappropriate at this time.

- Don Park

Don Park

unread,
Jul 16, 2012, 12:24:52 AM7/16/12
to rest...@googlegroups.com
If Stream.Length throws NotSupportedException then do not remove Content-Length header from request.

s/do not remove/remove/ 

akoeplinger

unread,
Jul 19, 2012, 1:02:30 PM7/19/12
to rest...@googlegroups.com
I think my problem is related, as I'm also using the asynchronous API and AddFile(): https://groups.google.com/forum/?fromgroups#!topic/restsharp/Q0hCjOBUjrg
Not sure if the overload will suffice in my case though.

sujit singh

unread,
Mar 22, 2013, 6:23:37 AM3/22/13
to rest...@googlegroups.com
Hi,

I am looking for something like this for many many days.. I have overloaded as you said RestRequest Class.

And calling like this

request.AddFile("file", Writer, filename, "image/jpeg", fileData.Length);

Also I have a function like this

    public void streamWriterS(System.IO.Stream str)
        {
          // What To WRITER HERE???
        }
I am just not getting how to achieve this? can someone explain me?

Thanks
Sujit

Aldo Faisal Umam

unread,
Oct 6, 2025, 6:00:59 AM (11 days ago) Oct 6
to RestSharp
Thanks, Suji for sharing such a nice blog post. It was very useful for my website.
Reply all
Reply to author
Forward
0 new messages