【问题标题】:Browser crashes while downloading large size files下载大文件时浏览器崩溃
【发布时间】:2015-09-05 23:26:06
【问题描述】:

我有一个 web api,它从 azure 读取文件并将其下载到字节数组中。客户端收到此字节数组并将其下载为 pdf。这不适用于大文件。 我无法弄清楚如何将字节从 web api 分块发送到客户端。

下面是web api代码,它只是将字节数组返回给客户端:

        CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
        blockBlob.FetchAttributes();
        byte[] data = new byte[blockBlob.Properties.Length];
        blockBlob.DownloadToByteArray(data, 0);
        return report;

客户端代码在ajax请求完成时获取数据,创建一个超链接并设置下载文件的下载属性:

var a = document.createElement("a");
a.href = 'data:application/pdf;base64,' + data.$value;;
a.setAttribute("download", filename);

1.86 MB 的文件出现错误。

浏览器显示消息: 显示网页时出现问题。要继续,请重新加载网页。

【问题讨论】:

  • 使用 URL.createObjectURL() 代替 dataURLs
  • 您可以按原样发布您的代码吗?没有它就很难看到潜在的问题。错误是什么?是服务器端错误,客户端错误,你找到文件大小的阈值了吗?我已经完成了从 Azure 存储下载多个 GB 文件大小的项目,所以我知道那里没有限制。
  • @ManOVision 我添加了一些代码。谢谢。
  • @dandavis 你是对的。谢谢。

标签: javascript c# asp.net-web-api azure-storage azure-blob-storage


【解决方案1】:

问题很可能是您的服务器在这些大文件上的内存不足。不要将整个文件加载到变量中,然后将其作为响应发送出去。这会导致双重下载,您的服务器必须从 azure 存储下载它并将其保存在内存中,然后您的客户端必须从服务器下载它。你可以做一个流来流复制,这样内存就不会被占用。这是来自您的 WebApi 控制器的示例。

public async Task<HttpResponseMessage> GetPdf()
{
    //normally us a using statement for streams, but if you use one here, the stream will be closed before your client downloads it.

    Stream stream;
    try
    {
        //container setup earlier in code

        var blockBlob = container.GetBlockBlobReference(fileName);

        stream = await blockBlob.OpenReadAsync();

        //Set your response as the stream content from Azure Storage
        response.Content = new StreamContent(stream);
        response.Content.Headers.ContentLength = stream.Length;

        //This could change based on your file type
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    }
    catch (HttpException ex)
    {
        //A network error between your server and Azure storage
        return this.Request.CreateErrorResponse((HttpStatusCode)ex.GetHttpCode(), ex.Message);
    }
    catch (StorageException ex)
    {
        //An Azure storage exception
        return this.Request.CreateErrorResponse((HttpStatusCode)ex.RequestInformation.HttpStatusCode, "Error getting the requested file.");
    }
    catch (Exception ex)
    {
        //catch all exception...log this, but don't bleed the exception to the client
        return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Bad Request");
    }
    finally
    {
        stream = null;
    }
}

我已经(几乎完全)使用了这段代码,并且能够下载超过 1GB 大小的文件。

【讨论】:

猜你喜欢
  • 2015-07-11
  • 2016-12-04
  • 1970-01-01
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多