如何正确编写从Web API接收的文件

时间:2018-10-20 22:46:27

标签: c# asp.net-core-webapi

我尝试制作一个简单的Web API来接收来自服务器的文件。

这是服务器部分:

var result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(itemPath, FileMode.Open, FileAccess.Read);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = 
      new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = 
      new ContentDispositionHeaderValue("attachment") { FileName = itemPath };
return result;

客户端部分:

var client = new HttpClient();
var responce = Task.Run(() => client.GetAsync(@"https://localhost:...")).Result;
var bytes = Task.Run(() => responce.Content.ReadAsByteArrayAsync()).Result;
var writer = 
  new BinaryWriter(new FileStream(fileName, FileMode.CreateNew, FileAccess.Write));
writer.Write(bytes);
writer.Close();

以及书面文件内容:

{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,
"minorRevision":-1},"content":{"headers":[{"key":"Content-Type","value":["application/octet-stream"]},{"key":"Content-Disposition",
"value":["attachment; filename=\"=?utf-8?B?ZDpcTGlicmFyeVBhdGhc0J/QsNGH0LXQutC+XEV4YW1wbGUgR
DVcQ2QxN1xDTElQQlJEXE1haW5Gcm0ucGFz?=\""]}]},"statusCode":200,
"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}

我希望此文件包含服务器本身的文件,但不包含描述它的JSON。

我想念什么?

1 个答案:

答案 0 :(得分:5)

响应的内容不应是HttpResponseMessage的JSON表示形式。

Asp.net核心Web API正在像普通模型对象一样读取HttpResponseMessage类并将其序列化为JSON。

重构服务器端代码以在控制器中使用建议的语法

public IActionResult MyAction(...) {
    //...
    var stream = new FileStream(itemPath, FileMode.Open, FileAccess.Read);
    return File(stream, "application/octet-stream", "desired file name here");
}

返回从IActionResult派生的FileStreamResult

在客户端,请尝试避免阻止诸如.Result之类的呼叫。还不清楚为什么已经可以等待异步调用时将其封装在Task.Run中。

始终保持代码异步

var client = new HttpClient();
var response = await client.GetAsync(@"https://localhost:..."); ;
var bytes = await response.Content.ReadAsByteArrayAsync();
var fileName = response.Content.Headers.ContentDisposition.FileName;
using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write)) {
    await stream.WriteAsync(bytes, 0, bytes.Length);
}

响应内容本可以作为流读取并直接复制到文件流中

var client = new HttpClient();
var response = await client.GetAsync(@"https://localhost:..."); ;
var stream = await response.Content.ReadAsStreamAsync();
var fileName = response.Content.Headers.ContentDisposition.FileName;
using (var fileStream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write)) {
    await stream.CopyToAsync(fileStream);
}