通过 WCF 服务接收大文件
Receive large files via WCF service
我有一个应该接收大文件的应用程序,这就是我使用 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
配合使用效果很好,但我想使用更现代的方法。我确定我做错了什么,请指教:
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());
}
}
}
已解决:只需单独使用 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();
}
我有一个应该接收大文件的应用程序,这就是我使用 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
配合使用效果很好,但我想使用更现代的方法。我确定我做错了什么,请指教:
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());
}
}
}
已解决:只需单独使用 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();
}