我对流、返回值和处置感到困惑。 即我使用流并想从方法返回流。下一个代码:
public async Task<HttpResponseMessage> GetOverlayAsync(string fileUrl, string language, string strOCR)
{
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
using (var stream = new FileStream(@"D:\_forTest.jpg", FileMode.Open))
{
length = stream.Length;
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = Path.GetFileName("_forTest.jpg");
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = length;
return result;
}
}
和
public async Task<HttpResponseMessage> GetOverlayAsync(string fileUrl, string language, string strOCR)
{
long length = 0;
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
using (var stream = new FileStream(@"D:\_forTest.jpg", FileMode.Open))
{
length = stream.Length;
result.Content = new StreamContent(stream);
}
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = Path.GetFileName("_forTest.jpg");
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = length;
return result;
}
返回 504 状态代码:
读取响应() 失败:服务器未返回完整响应 对于此请求。服务器返回 0 个字节。
所以,据我了解,当我们从方法出去时,流被处理
掉了如果我根本不调用"处置":
public async Task<HttpResponseMessage> GetOverlayAsync(string fileUrl, string language, string strOCR)
{
long length = 0;
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
var stream = new FileStream(@"D:\_forTest.jpg", FileMode.Open);
length = stream.Length;
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = Path.GetFileName("_forTest.jpg");
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = length;
return result;
}
有时我得到该文件被另一个进程阻止。如何正确制作?
一些背景:一般来说,如果你想流一个文件的内容,你要做的是从文件流中读取并写入HTTP响应的输出流。 例:
using (var source = new FileStream(...))
{
byte[] buffer = new byte[4096];
int byteCount;
while ((byteCount = await source.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await output.WriteAsync(buffer, 0, byteCount);
}
}
现在,在您的特定情况下,您正在使用一个框架/模式,该框架/模式要求您将包含内容的流传递给它,而不是允许您自己写入输出。在这种情况下,您被迫将释放流的责任转移到处理程序方法的调用者。
细节:如果您的问题是文件被锁定,那么您可以在打开流时允许共享读/写访问:
var stream = new FileStream(@"D:\_forTest.jpg", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
这将允许其他进程在您读取文件时对文件具有读取和写入访问权限。
编辑:正如@Evk所指出的,更安全的选择是只与读者共享访问权限(尝试打开文件进行写入将被拒绝):
var stream = new FileStream(@"D:\_forTest.jpg", FileMode.Open, FileAccess.Read, FileShare.Read);
改进:如果您的文件适合内存,明智的做法是对其进行内存缓存,而不是直接从磁盘流式传输。如果您有数千个同时请求来获取此文件,那么您的磁盘将成为一个巨大的瓶颈。使用具有保留/过期策略的缓存,并在缓存未命中时读取和缓存整个文件。这样,您还可以最小化打开文件句柄的窗口(打开、线性 I/O 读取、关闭;非常快)。