释放并返回值



我对流、返回值和处置感到困惑。 即我使用流并想从方法返回流。下一个代码:

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 读取、关闭;非常快)。

最新更新