【问题标题】:Download file from object storage through asp net core通过asp net core从对象存储中下载文件
【发布时间】:2018-08-18 01:50:51
【问题描述】:

我将文件存储在 Openstack Swift 容器(对象存储)中。我通常通过 API 访问它们,如下所示:

 _oApi.Swift.GetObject(containerName, fileName, outputStream);

现在,我有一个用 ASP NET Core 2.0 编写的 Web 界面,我希望用户能够下载存储在 Swift 容器中的文件。

以下代码有一个缺点,文件首先下载到我的网络服务器,然后才会在客户端开始下载。

[HttpGet]
public IActionResult Download(string id)
{
    Response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}");
    Response.Headers.Add("Content-Length", filseSize);
    Response.Headers.Add("Content-Type", "application/octet-stream");

    _oApi.Swift.GetObject(containerName, fileName, Response.Body);
    return View();
}

如何在不将结果缓存在网络服务器上的情况下将下载直接流式传输到客户端浏览器?

PS:我正在尝试使用 20mb 或更大的文件,因为此代码适用于小文件。

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc openstack-swift


    【解决方案1】:

    直接将流作为结果传递,而不是先将其保存到磁盘。

    以下示例结构直接取自project repository on GitHub

    [HttpGet]
    public async Task<IActionResult> Download(string id) {
    
        //...
    
        Response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}");
    
        var response = await _oApi.Swift.GetObject(containerName, fileName);
    
        if(response.IsSuccess) {
            return new FileStreamResult(response.Stream, "application/octet-stream");
        }
    
        return new NotFoundResult();
    }
    

    还有这个例子是根据你的例子再次采样的

    public async Task<IActionResult> Download(string id) {
        var headObject = await _oApi.Swift.HeadObject(containerId, id);
    
        if (headObject.IsSuccess && headObject.ContentLength > 0) {
            var fileName = headObject.GetMeta("Filename");
            var contentType = headObject.GetMeta("Contenttype");
    
            Response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}");
    
            var stream = new BufferedHTTPStream((start, end) => {
                using (var response = _oApi.Swift.GetObjectRange(containerId, objectId, start, end).Result) {
                    var ms = new MemoryStream();
                    response.Stream.CopyTo(ms);
                    return ms;
               }    
            }, () => headObject.ContentLength);
    
            return new FileStreamResult(stream, contentType);
        }
    
        return new NotFoundResult();
    }
    

    【讨论】:

    • 谢谢。在打开问题之前,我已经尝试过这些示例。由于请求的结果存储在控制器的流中,它首先匹配服务器内存中的结果,然后返回 FileStreamResult。
    猜你喜欢
    • 2017-08-02
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2022-12-24
    相关资源
    最近更新 更多