处理并返回值

时间:2017-04-12 09:48:16

标签: c# stream dispose using memorystream

我与溪流混淆,返回价值和处置。即我使用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个字节。

所以,据我所知,当我们从方法出去时,流被处理

如果我根本不打电话给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;
    }

有时我得到该文件被另一个进程阻止。如何正确使用?

1 个答案:

答案 0 :(得分: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-cache而不是直接从磁盘流式传输是明智的。如果您有数千个同时请求来获取此文件,您的磁盘将成为一个巨大的瓶颈。使用具有保留/到期策略的缓存,并在缓存未命中时读取和缓存整个文件。这样,您还可以最小化打开文件句柄的窗口(打开,线性I / O读取,关闭;非常快)。