【发布时间】:2018-10-18 20:23:08
【问题描述】:
我有一个 API HTTPGET 可以从另一个 API 检索文件,然后将其吐出。这适用于较小的文件,但我遇到的问题是检索到的文件可能相当大(最多 2gb),并且 MemoryStream 是一个限制。任何想法如何在不使用磁盘的情况下流式传输文件内容并避免“内存不足”异常?
控制器:
[Route("{id}/file", Name = "GetContentFile")]
[HttpGet]
public IHttpActionResult GetContentFile(string id)
{
if (String.IsNullOrEmpty(id))
return BadRequest();
ContentFile cfl = new ContentFile();
var ret = new HttpResponseMessage(HttpStatusCode.OK);
try
{
cfl = otcrepo.GetContentFile(id);
var mstream = new MemoryStream(cfl.Data);
ret.Content = new StreamContent(mstream);
ret.Content.Headers.ContentType = new MediaTypeHeaderValue(cfl.ContentType);
ret.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
}
catch
{
return InternalServerError();
}
if (cfl != null)
{
ResponseMessageResult responseMessageResult = ResponseMessage(ret);
return responseMessageResult;
}
else
{
return NotFound();
}
}
型号:
public class ContentFile
{
public string Filename { get; set; }
public byte[] Data { get; set; }
public StreamContent DataStream { get; set; }
public string ContentType { get; set; }
}
存储库调用:
public ContentFile GetContentFile(string id)
{
ContentFile fl = new ContentFile();
using (var htc = new HttpClient())
{
var response = htc.GetAsync(ConfigurationManager.AppSettings["BaseUrl"] + "/api/v2/nodes/" + id + "/content/").Result;
fl.Data = response.Content.ReadAsByteArrayAsync().Result;
fl.ContentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
}
return fl;
}
谢谢。
【问题讨论】:
-
不使用内存?
-
如果你不愿意使用内存或磁盘,我看不出这是怎么可能的。其他选择是什么(除了内存或磁盘)?
-
我会改写我的问题,因为正如您所指出的,必须使用一些内存。如何在避免outofmemory异常的同时做到这一点?
-
哇,等一下,你还有其他问题要担心。 您在异步任务上使用
.Result。那是非常危险的!这可能会使您的服务器死锁。出于某种原因,它是异步的;你必须await那个。在尝试快速获取代码之前先获取代码。 -
除此之外,我不明白你为什么要这样做。您说您不想将文件放入内存中,但是您正在将其作为字节数组读入内存。如果要流式传输它,为什么要将其移动到字节数组中,然后将流放在字节数组的顶部?这是一件非常奇怪的事情。你为什么不直接打电话给
GetResponseStream?你想要一个流,好吧,得到一个流。不要获取字节数组并在其上构建流。
标签: c# .net asp.net-web-api asp.net-web-api2