通过ASP Net Core从对象存储下载文件

时间:2018-08-17 15:10:18

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

我将文件存储在Openstack Swift容器(对象存储)中。我通常通过这样的API来访问它们:

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

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

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

[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();
}

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

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

1 个答案:

答案 0 :(得分:0)

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

以下示例结构直接取自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();
}