2017-04-12 108 views
0

我对流感到困惑,返回值和处置。即我使用Stream并想从方法返回流。下面的代码:配置并返回值

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状态码:

ReadResponse()失败:服务器未返回为此请求完全反应 。服务器返回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; 
    } 

有时我得到的文件被阻止:

所以,按照我的理解,流当我们从法

出去如果我不调用Dispose在所有配置另一个过程。如何正确使用?

+0

你的例子是否真的编译?这些方法被标记为“async”,但方法中没有“await”。 – Sean

+0

我在 –

+0

之前删除了不必要的代码尝试打开文件流如下:'new FileStream(@“D:\\ _ forTest.jpg”,FileMode.Open,FileAccess.Read,FileShare.Read);'当然不要配置它(发送给客户后会自动为您处理)。当你只做'新的FileStream(...,FileMode.Open)' - 它相当于'新的FileStream(...,FileMode.Open,FileAccess.ReadWrite,FileShare。读)“,并且这将防止随后打开相同的文件,即使是来自相同的进程。 – Evk

回答

2

一些背景资料: 一般来说,如果你想流的文件的内容,你想要做的是从文件流读取和写入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); 

改进: 如果你的文件适合在内存中,mem缓存而不是直接从磁盘进行流式传输将是明智之举。如果您有数千个并发请求来获取此文件,则您的磁盘将成为一个巨大的瓶颈。使用具有保留/过期策略的缓存并读取并缓存缓存未命中的整个文件。这样,您还可以最小化文件句柄打开的窗口(打开,线性I/O读取,关闭;非常快)。

+0

的确如此,但最好指定'FileShare.Read',因为在阅读过程中,您并不是真的想要有人在写文件,而且在这种特殊情况下您并不需要这些。 – Evk

+0

好点,但要看。试图更新文件时是否要阻止写入?或者,如果某些用户得到损坏的图像,但是可以更新图像而不停止服务器? –

+0

我认为,如果“某些用户得到了一个损坏的图像”,它永远不会确定:) :) – Evk