处置和 return 值
Dispose and return value
我对流感到困惑,return 值和处置。 IE。我使用 Stream 并希望 return 从方法流式传输。下一个代码:
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;
}
returns 504状态码:
ReadResponse() failed: The server did not return a complete response
for this request. Server returned 0 bytes.
因此,据我了解,当我们从方法中退出时,流被处理掉
如果我根本不调用 Dispose:
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);
}
}
现在,在您的特定情况下,您使用的是 framework/pattern,这需要您将内容流传递给它,而不是让您自己写入输出。在这种情况下,您被迫将处理流的责任转移给处理程序方法的调用者。
规格:
如果您的问题是文件被锁定,那么您可以在打开流时允许共享 read/write 访问:
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);
改进:
如果您的文件适合内存,明智的做法是将其内存缓存而不是直接从磁盘流式传输。如果您同时有数千个请求来获取此文件,您的磁盘将成为一个巨大的瓶颈。使用具有 retention/expiration 策略的缓存,并在缓存未命中时读取并缓存整个文件。通过这种方式,您还可以最小化打开文件句柄的 window(打开,线性 I/O 读取,关闭;非常快)。
我对流感到困惑,return 值和处置。 IE。我使用 Stream 并希望 return 从方法流式传输。下一个代码:
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;
}
returns 504状态码:
ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.
因此,据我了解,当我们从方法中退出时,流被处理掉
如果我根本不调用 Dispose:
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);
}
}
现在,在您的特定情况下,您使用的是 framework/pattern,这需要您将内容流传递给它,而不是让您自己写入输出。在这种情况下,您被迫将处理流的责任转移给处理程序方法的调用者。
规格: 如果您的问题是文件被锁定,那么您可以在打开流时允许共享 read/write 访问:
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);
改进: 如果您的文件适合内存,明智的做法是将其内存缓存而不是直接从磁盘流式传输。如果您同时有数千个请求来获取此文件,您的磁盘将成为一个巨大的瓶颈。使用具有 retention/expiration 策略的缓存,并在缓存未命中时读取并缓存整个文件。通过这种方式,您还可以最小化打开文件句柄的 window(打开,线性 I/O 读取,关闭;非常快)。