如何将 HttpResponseMessage 的 ByteArrayContent 下载为 zip

Posted

技术标签:

【中文标题】如何将 HttpResponseMessage 的 ByteArrayContent 下载为 zip【英文标题】:How to download ByteArrayContent of HttpResponseMessage as zip 【发布时间】:2015-04-16 17:15:26 【问题描述】:

我在客户端使用 Web Api (C#) 和 angular.js。 我需要下载服务器响应内容(zip 的 ByteArrayContent)。 我在服务器上有这个方法:

public HttpResponseMessage Download(DownloadImagesInput input)
        
            if (!string.IsNullOrEmpty(input.ImageUrl))
            
                byte[] imageBytes = GetByteArrayFromUrl(input.ImageUrl);

                ZipManager manager = new ZipManager();
                HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                byte[] zipBytes;


                zipBytes = string.IsNullOrEmpty(input.QrCode) ? manager.ZipFiles(imageBytes) 
                                                              : manager.ZipFiles(imageBytes, input.QrCode);

                result.Content = new ByteArrayContent(zipBytes);


                result.Content.Headers.ContentType =
                                    new MediaTypeHeaderValue("application/zip");
                return result;

            

            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
        

ZipManager 是我的服务,它只返回 zip 文件的字节数组。 我需要在客户端下载这个 zip 存档。 这是我的客户:

$apiService.downloadZip( 'ImageUrl': $scope.currentImage, 'QrCode': str ).then(function (response) 

            var hiddenElement = document.createElement('a');

            hiddenElement.href = 'data:application/zip,' + response.data;
            hiddenElement.target = '_blank';
            hiddenElement.download = 'images.zip';
            hiddenElement.click();
        );

结果:下载 zip 文件但我无法打开它,文件格式无效

在服务器上创建的zip文件是好的,我只是通过直接将他从服务器保存到磁盘来检查它... 需要帮助。

【问题讨论】:

【参考方案1】:

我找到了解决办法:

服务器:

1.将字节数组转换为base64字符串:

string base64String = System.Convert.ToBase64String(zipBytes, 0, zipBytes.Length);

2.result内容是StringContent而不是ByteArrayContent:

result.Content = new StringContent(base64String);

客户:

$apiService.downloadZip( 'ImageUrl': $scope.currentImage, 'QrCode': str ).then(function (response) 
            var hiddenElement = document.createElement('a');

            hiddenElement.href = 'data:application/octet-stream;charset=utf-8;base64,' + response.data;
            hiddenElement.target = '_blank';
            hiddenElement.download = 'images.zip';
            hiddenElement.click();
        );

【讨论】:

我无法在 IE11 或 edge 中下载文件。这个逻辑可能需要稍微调整一下。【参考方案2】:

下面是我用来下载任何类型文件的函数代码

var downloadFile = function (filename) 
    enableSpinner();
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
    ifr.src = document.location.pathname + "api/FileIo/Download?filename='" + escape(filename) + "'";
    ifr.onload = function () 
        document.body.removeChild(ifr);
        ifr = null;
    ;
;

及其服务器端代码

[HttpGet]
        public HttpResponseMessage Download(string filename)
        
            filename = filename.Replace("\\\\", "\\").Replace("'", "").Replace("\"", "");
            if (!char.IsLetter(filename[0]))
            
                filename = filename.Substring(2);
            

            var fileinfo = new FileInfo(filename);
            if (!fileinfo.Exists)
            
                throw new FileNotFoundException(fileinfo.Name);
            

            try
            
                var excelData = File.ReadAllBytes(filename);
                var result = new HttpResponseMessage(HttpStatusCode.OK);
                var stream = new MemoryStream(excelData);
                result.Content = new StreamContent(stream);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                
                    FileName = fileinfo.Name
                ;
                return result;
            
            catch (Exception ex)
            
                return Request.CreateResponse(HttpStatusCode.ExpectationFailed, ex);
            
        

您可以用 zip 部分替换 excel 部分并完成...

【讨论】:

以上是关于如何将 HttpResponseMessage 的 ByteArrayContent 下载为 zip的主要内容,如果未能解决你的问题,请参考以下文章

如何从 javascript 中的 C# HttpResponseMessage 读取内容?

如何在 Web API 中将 HttpResponse 设置为 HttpResponseMessage

将内容放在 HttpResponseMessage 对象中?

如何从 HttpResponseMessage 中获取特定的标头值

如何确定是不是使用 HttpClient 从缓存中完成了 HttpResponseMessage

如何在 HttpResponseMessage 上设置响应 cookie?