C# 通过asp net内核从对象存储下载文件

C# 通过asp net内核从对象存储下载文件,c#,asp.net-core,asp.net-core-mvc,openstack-swift,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(

我将文件存储在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或更大的文件,因为此代码可以很好地处理小文件。

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

下面的示例结构直接取自

[HttpGet]
公共异步任务下载(字符串id){
//...
Add(“内容处置”,$“附件;文件名={filename}”);
var response=await_oApi.Swift.GetObject(containerName,文件名);
if(response.issucess){
返回新的FileStreamResult(response.Stream,“应用程序/八位字节流”);
}
返回新的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();
}
公共异步任务下载(字符串id){
var headObject=wait_oApi.Swift.headObject(containerId,id);
if(headObject.issucess&&headObject.ContentLength>0){
var fileName=headObject.GetMeta(“文件名”);
var contentType=headObject.GetMeta(“contentType”);
Add(“内容处置”,$“附件;文件名={filename}”);
var stream=新的BufferedHTTPStream((开始,结束)=>{
使用(var response=_oApi.Swift.GetObjectRange(containerId、objectId、start、end).Result){
var ms=新内存流();
response.Stream.CopyTo(ms);
返回ms;
}    
},()=>headObject.ContentLength);
返回新的FileStreamResult(流,contentType);
}
返回新的NotFoundResult();
}

谢谢。在开始发行之前,我试过这些样品。由于请求的结果存储在控制器上的流中,因此在返回FileStreamResult之前,它首先在服务器内存中匹配结果。
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();
}