通过WCF服务接收大文件

时间:2016-05-14 11:30:47

标签: c# .net wcf rest dotnet-httpclient

我有一个应该接收大文件的应用程序,这就是我使用stream参数的原因。

服务合同:

[ServiceContract]
public interface IFile
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/Upload?fileName={fileName}&requestType={requestType}", ResponseFormat = WebMessageFormat.Json)]
    FileMetadata Upload(string fileName, RequestType requestType, Stream stream);
}

实现:

public FileMetadata Upload(string fileName, RequestType requestType, Stream stream)
{
    var contract = GetContract(fileName, requestType, stream);
    ...
}

private static FileUploadRequest GetContract(string fileName, RequestType requestType, Stream content)
{
    var ms = new MemoryStream();
    content.CopyTo(ms);
    return new FileUploadRequest
    {
        Filename = fileName,
        RequestType = requestType,
        Content = ms.ToArray()
    };
}

但是对于流我收到垃圾信息(边界等),传输XML的样本是:

--a288ea6c-376a-4c7e-9680-39199e34082c
Content-Disposition: form-data

<Doc> ... rest of XML

如何传输流本身?我应该删除客户端边界还是截断服务器端边界?因为这个服务也应该从JS中使用,我不知道它是否包含这样的附加信息或者没有。

客户端发送如下请求:

public async Task<FileMetadata> Upload(string fileName, RequestType requestType, Stream stream)
{
    var requestUri = $"Upload?fileName={fileName}&requestType={requestType}";
    using (var requestContent = new MultipartFormDataContent())
    {
        requestContent.Add(new StreamContent(stream));
        var response = await _client.PostAsync(requestUri, requestContent).ConfigureAwait(false);
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            return JsonConvert.DeserializeObject<FileMetadata>(responseContent);
        }
    }
    throw new Exception();
}

它适用于HttpWebRequest,但我想使用更现代的apporach。我确定我做错了,请建议:

public FileMetadata Upload(string fileName, RequestType requestType, Stream stream)
{
    var requestUri = $"Upload?fileName={fileName}&requestType={requestType}";
    var request = WebRequest.CreateHttp(new Uri(_client.BaseAddress, requestUri));
    request.Method = "POST";
    request.AllowWriteStreamBuffering = false;
    request.ContentLength = stream.Length;
    using (var requestStream = request.GetRequestStream())
    {
        stream.CopyTo(requestStream);
    }
    using (var response = (HttpWebResponse) request.GetResponse())
    {
        if (response.StatusCode != HttpStatusCode.OK)
        {
            throw new Exception();
        }
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            return JsonConvert.DeserializeObject<FileMetadata>(sr.ReadToEnd());
        }
    }
}

1 个答案:

答案 0 :(得分:0)

已解决:只需单独使用StreamContent,而无需包裹MultipardFormDataContent。代码示例:

public async Task<FileMetadata> Upload(string fileName, RequestType requestType, Stream stream)
{
    var requestUri = $"Upload?fileName={fileName}&requestType={requestType}";
    var response = await _client.PostAsync(requestUri, new StreamContent(stream)).ConfigureAwait(false);
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        return JsonConvert.DeserializeObject<FileMetadata>(responseContent);
    }
    throw new Exception();
}