【问题标题】:Web API: Download Multiple Files SeparatelyWeb API:分别下载多个文件
【发布时间】:2019-01-31 06:24:57
【问题描述】:

我有一个 Web Api 控制器方法,它获取传递的文档 ID,它应该为那些请求的 ID 单独返回文档文件。我已经尝试了以下链接中接受的答案来实现此功能,但它不起作用。我不知道我哪里做错了。

What's the best way to serve up multiple binary files from a single WebApi method?

我的 Web API 方法,

   public async Task<HttpResponseMessage> DownloadMultiDocumentAsync( 
             IClaimedUser user, string documentId)
    {
        List<long> docIds = documentId.Split(',').Select(long.Parse).ToList();
        List<Document> documentList = coreDataContext.Documents.Where(d => docIds.Contains(d.DocumentId) && d.IsActive).ToList();

        var content = new MultipartContent();
        CloudBlockBlob blob = null;

        var container = GetBlobClient(tenantInfo);
        var directory = container.GetDirectoryReference(
            string.Format(DirectoryNameConfigValue, tenantInfo.TenantId.ToString(), documentList[0].ProjectId));

        for (int docId = 0; docId < documentList.Count; docId++)
        {
            blob = directory.GetBlockBlobReference(DocumentNameConfigValue + documentList[docId].DocumentId);
            if (!blob.Exists()) continue;

            MemoryStream memStream = new MemoryStream();
            await blob.DownloadToStreamAsync(memStream);
            memStream.Seek(0, SeekOrigin.Begin);
            var streamContent = new StreamContent(memStream);
            content.Add(streamContent);

        }            
        HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
        httpResponseMessage.Content = content;
        httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        httpResponseMessage.StatusCode = HttpStatusCode.OK;
        return httpResponseMessage;
    }

我尝试使用 2 个或更多文档 ID,但只下载了一个文件,而且格式也不正确(无扩展名)。

【问题讨论】:

  • 我知道这将是 2 年。你找到解决方案了吗?我遇到了同样的问题。你能分享你的发现吗?

标签: c# azure web-applications asp.net-web-api2 httpresponsemessage


【解决方案1】:

压缩是唯一可以在所有浏览器上获得一致结果的选项。 MIME/多部分内容用于电子邮件消息 (https://en.wikipedia.org/wiki/MIME#Multipart_messages),它从未打算在 HTTP 事务的客户端接收和解析。有些浏览器确实实现了它,有些则没有。

或者,您可以更改您的 API 以接收单个 docId,并从您的客户端为每个 docId 迭代您的 API。

【讨论】:

  • @Mehdi,我已经尝试过压缩选项,它工作正常,但这里的要求是它应该单独下载,所以可能吗?
  • 我试图解释 mime/multipart 在浏览器中的实现不一致,并且不能保证它在同一浏览器的未来版本中始终如一地工作。例如您的解决方案可能适用于 Firefox,但不适用于 Chrome;而且,也不能保证它会在未来的 Firefox 版本中继续工作。我建议的替代方案是我的答案的后半部分 - 您可以更改您的 API 以接收单个 docId 并从您的客户端为每个 docId 迭代您的 API 吗?
  • 我也有一种下载单个文档的方法。现在用户的需求是单独下载多个文档,这就是我为此做研发的原因。无论如何,非常感谢你的解释,但如果你能提供一些示例代码用于这个多文档下载(没问题,即使它只能在一个浏览器中工作),请帮助我。
  • 不知道为什么您觉得为循环中的每个 docId 一次调用一个 API 会产生不同的最终结果。这将为您提供多文档下载功能 - 以跨浏览器兼容的方式。在http中,一个请求只能有一个响应。客户端是 javascript/Web 应用程序吗?您是否也尝试过使用 Firefox 自己的解决方案?据我了解,Firefox 是唯一支持它的浏览器,但该支持在 2013 年中断(“截至 Firefox 版本 22,Mozilla 已删除对多部分混合/替换的支持”bugs.launchpad.net/evergreen/+bug/1198983)。
  • @MdAslam 是的,我认为 Mehdi 是对的。您可以在前端使用循环来下载多个文件。你能分享你的前端代码吗?我可以帮忙吗?
【解决方案2】:

我认为唯一的方法是压缩所有文件,然后下载一个压缩文件。我想您可以使用 dotnetzip 包,因为它易于使用。

一种方法是,您可以先将文件保存在磁盘上,然后通过流式传输 zip 进行下载。另一种方法是,您可以将它们压缩到内存中,然后在流中下载文件

public ActionResult Download()
{
    using (ZipFile zip = new ZipFile())
    {
        zip.AddDirectory(Server.MapPath("~/Directories/hello"));

        MemoryStream output = new MemoryStream();
        zip.Save(output);
        return File(output, "application/zip", "sample.zip");
    }  
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多