22

I am using RestSharp (version 105.2.3.0 in Visual Studio 2013, .net 4.5) to call a NodeJS hosted webservice. One of the calls I need to make is to upload a file. Using a RESTSharp request, if I retrieve the stream from my end into a byte array and pass that to AddFile, it works fine. However, I would much rather stream the contents and not load up entire files in server memory (the files can be 100's of MB).

If I set up an Action to copy my stream (see below), I get an exception at the "MyStream.CopyTo" line of System.Net.ProtocolViolationException (Bytes to be written to the stream exceed the Content-Length bytes size specified). This exception is thrown within the Action block after client.Execute is called.

From what I read, I should not be manually adding a Content-Length header, and it doesn't help if I do. I have tried setting CopyTo buffer too small and large values, as well as omitting it entirely, to no avail. Can somebody give me a hint on what I've missed?

    // Snippet...
    protected T PostFile<T>(string Resource, string FieldName, string FileName,
        string ContentType, Stream MyStream, 
        IEnumerable<Parameter> Parameters = null) where T : new()
    {
        RestRequest request = new RestRequest(Resource);
        request.Method = Method.POST;

        if (Parameters != null)
        {
            // Note:  parameters are all UrlSegment values
            request.Parameters.AddRange(Parameters);
        }

        // _url, _username and _password are defined configuration variables
        RestClient client = new RestClient(_url);
        if (!string.IsNullOrEmpty(_username))
        {
            client.Authenticator = new HttpBasicAuthenticator(_username, _password);
        }

        /*
        // Does not work, throws System.Net.ProtocolViolationException,
        // Bytes to be written to the stream exceed the 
        // Content-Length bytes size specified.
        request.AddFile(FieldName, (s) =>
        {
            MyStream.CopyTo(s);
            MyStream.Flush();
        }, FileName, ContentType);
        */

        // This works, but has to load the whole file in memory
        byte[] data = new byte[MyStream.Length];
        MyStream.Read(data, 0, (int) MyStream.Length);
        request.AddFile(FieldName, data, FileName, ContentType);

        var response = client.Execute<T>(request);

        // check response and continue...
    }
3
  • 1
    I just discovered the same problem. My line request.AddFile("file", stream => data.CopyTo(stream), fileName) got broken with RestSharp version 105.2.0+ . When downgrading to 105.1.0 it works fine. Haven't had time to investigate the changes in the git-repo yet... Commented Oct 19, 2015 at 8:28
  • I have this problem too. Downgrading to 105.1.0 helped, but I also added a comment to old issue on github Commented Oct 23, 2015 at 12:57
  • You can use AddFileBytes is some sort of wrapper Commented Sep 16, 2016 at 15:25

2 Answers 2

18

I had the same issue. I ended up using the .Add() on the Files collection. It has a FileParameter param which has the same params as AddFile(), you just have to add the ContentLength:

var req = GetRestRequest("Upload", Method.POST, null);
//req.AddFile("file",
//    (s) => {
//        var stream = input(imageObject);
//        stream.CopyTo(s);
//        stream.Dispose();
//    },
//    fileName, contentType);

req.Files.Add(new FileParameter {
    Name = "file",
    Writer = (s) => {
        var stream = input(imageObject);
        stream.CopyTo(s);
        stream.Dispose();
    },
    FileName = fileName,
    ContentType = contentType,
    ContentLength = contentLength
});            
Sign up to request clarification or add additional context in comments.

3 Comments

what is the input ? I got error on this. how to declare it ?
@Root If you have your file as a byte[], you can convert it into a MemoryStream and refer to it. Worked like a charm for me: Stream stream = new MemoryStream(fileBytes); Then below just remove the line in question and refer to your new Stream object.
This is outdated. req.Files.Add no longer exists in v4.0
-3

The following code works for me for uploading a csv file using rest sharp. Web services API has been called.

var client = new RestClient(<YOUR API END URL >);
var request = new RestRequest(Method.POST) ;
request.AlwaysMultipartFormData = true;
request. AddHeader("Content-Type", "multipart/form-data");
request.AddHeader("X-API-TOKEN", <Your Unique Token - again not needed for certain calls>);
request.AddParameter(<Your parameters.....>);
request.AddFile("file", currentFileLocation, contentType);
request.AddParameter("multipart/form-data", fileName, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
var response = client.Execute(request);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.