RestSharp使用流添加文件

22

我正在使用RestSharp(在Visual Studio 2013,.net 4.5中版本为105.2.3.0)来调用托管在NodeJS上的Web服务。其中一个需要进行的调用是上传文件。使用RESTSharp请求,如果从我的端点检索流到字节数组并将其传递给AddFile,则可以正常工作。但是,我更希望流式传输内容,而不是在服务器内存中加载整个文件(文件可能达到数百MB)。

如果我设置一个操作来复制我的流(见下文),则会在“MyStream.CopyTo”行处抛出System.Net.ProtocolViolationException异常(要写入流中的字节超过指定的Content-Length字节大小)。此异常在调用client.Execute后的Action块中抛出。

从我读到的内容来看,我不应手动添加Content-Length标头,即使这样也没有帮助。我已尝试将CopyTo缓冲区设置为太小或太大的值,以及完全省略它,但都无济于事。有谁能给我一些提示,告诉我我错过了什么?

    // 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...
    }

1
我刚刚发现了同样的问题。我的代码行 request.AddFile("file", stream => data.CopyTo(stream), fileName) 在 RestSharp 版本 105.2.0+ 中出现了问题。当降级到 105.1.0 时,它可以正常工作。我还没有时间去研究 git-repo 中的更改... - anve
我也有这个问题。降级到105.1.0有所帮助,但我还在旧的github问题上添加了一条评论(https://github.com/restsharp/RestSharp/issues/70)。 - Dmitry
你可以使用AddFileBytes作为某种包装器。 - hpfs
2个回答

18

我遇到了同样的问题。最终,我使用了 Files 集合上的 .Add() 方法。它有一个 FileParameter 参数,该参数具有与 AddFile() 相同的参数,您只需要添加 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
});            

6
“input”是什么?我在这里遇到了错误。该怎样声明它呢? - Root
1
如果您的文件是一个 byte[],您可以将其转换为 MemoryStream 并引用它。这对我来说非常有效:Stream stream = new MemoryStream(fileBytes);然后只需删除相关行并引用您的新 Stream 对象即可。 - corbin
2
这已经过时了。req.Files.Add在v4.0中不再存在。 - Robert Barrueco

-1

下面的代码适用于我使用rest sharp上传csv文件。已调用Web服务API。

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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接