使用MemoryStream和ZipArchive将zip文件返回到asp.net web api中的客户端

Kob*_*_24 6 c# ajax memorystream ziparchive asp.net-web-api

我试图使用以下代码将zip文件从asp.net web api返回给客户端:

private byte[] CreateZip(string data)
{
    using (var ms = new MemoryStream())
    {
        using (var ar = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            var file = archive.CreateEntry("file.html");

            using (var entryStream = file.Open())
            using (var sw = new StreamWriter(entryStream))
            {
                sw .Write(value);
            }
        }
        return memoryStream.ToArray();
    }
}

public HttpResponseMessage Post([FromBody] string data)
{
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new ByteArrayContent(CreateZip(data));
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip, application/octet-stream");
    return result;
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,我收到以下错误:

ExceptionMessage":"值'application/zip,application/octet-stream'的格式无效."

这是JS代码:

$.ajax({
  type: "POST",
  url: url,
  data: data,
  dataType: application/x-www-form-urlencoded
});
Run Code Online (Sandbox Code Playgroud)

任何解释为什么会这样?我真的很喜欢你的帮助人员

use*_*165 9

$.ajax处理文本响应并尝试(utf-8)解码内容:您的zip文件不是文本,您将获得损坏的内容.jQuery不支持二进制内容,因此您需要使用链接并在jQuery上添加ajax传输或直接使用XmlHttpRequest.使用xhr,您需要设置xhr.responseType = "blob"和读取xhr.responseblob.

// with xhr.responseType = "arraybuffer"
var arraybuffer = xhr.response;
var blob = new Blob([arraybuffer], {type:"application/zip"});
saveAs(blob, "example.zip");

// with xhr.responseType = "blob"
var blob = xhr.response;
saveAs(blob, "example.zip");
Edit: examples:
Run Code Online (Sandbox Code Playgroud)

使用jquery.binarytransport.js (任何允许您下载Blob或ArrayBuffer的库都可以)

$.ajax({
  url: url,
  type: "POST",
  contentType: "application/json",
  dataType: "binary", // to use the binary transport
  // responseType:'blob', this is the default
  data: data,
  processData: false,
  success: function (blob) {
    // the result is a blob, we can trigger the download directly
    saveAs(blob, "example.zip");
  }
  // [...]
});
Run Code Online (Sandbox Code Playgroud)

使用原始的XMLHttpRequest,你可以看到这个问题,你只需要添加一个xhr.responseType = "blob"来获取blob.

我个人建议你在jQuery上使用ajax传输,这非常简单,你必须下载一个库,将它包含在项目中并编写: dataType: "binary".

这是使用DotNetZip(Ionic.Zip)的API代码:

   [HttpPost]
    public HttpResponseMessage ZipDocs([FromBody] string[] docs)
    {
        using (ZipFile zip = new ZipFile())
        {
            //this code takes an array of documents' paths and Zip them
            zip.AddFiles(docs, false, "");
            return ZipContentResult(zip);
        }
    }

    protected HttpResponseMessage ZipContentResult(ZipFile zipFile)
    {
        var pushStreamContent = new PushStreamContent((stream, content, context) =>
        {
          zipFile.Save(stream);
            stream.Close(); 
        }, "application/zip");

        return new HttpResponseMessage(HttpStatusCode.OK) { Content = pushStreamContent };
    }
Run Code Online (Sandbox Code Playgroud)


Fit*_*tch 5

这是对我有用的解决方案

C#面

public IActionResult GetZip([FromBody] List<DocumentAndSourceDto> documents)
{
    List<Document> listOfDocuments = new List<Document>();

    foreach (DocumentAndSourceDto doc in documents)
        listOfDocuments.Add(_documentService.GetDocumentWithServerPath(doc.Id));

    using (var ms = new MemoryStream())
    {
        using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            foreach (var attachment in listOfDocuments)
            {
                var entry = zipArchive.CreateEntry(attachment.FileName);

                using (var fileStream = new FileStream(attachment.FilePath, FileMode.Open))
                using (var entryStream = entry.Open())
                {
                    fileStream.CopyTo(entryStream);
                }
            }

        }
        ms.Position = 0;
        return File(ms.ToArray(), "application/zip");
    }

    throw new ErrorException("Can't zip files");
}
Run Code Online (Sandbox Code Playgroud)

不要错过ms.Position = 0;这里

正面(角度4):

downloadZip(datas: any) {
    const headers = new Headers({
        'Content-Type': 'application/json',
        'Accept': 'application/zip'
    });

    const options = new RequestOptions({ headers: headers, withCredentials: true, responseType: ResponseContentType.ArrayBuffer });
    const body = JSON.stringify(datas);
    return this.authHttp.post(`${environment.apiBaseUrl}api/documents/zip`, body, options)
        .map((response: Response) => {
            const blob = new Blob([response.blob()], { type: 'application/zip' });
            FileSaver.saveAs(blob, 'logs.zip');
        })
        .catch(this.handleError);
}
Run Code Online (Sandbox Code Playgroud)

现在,我可以将多个文件下载为zip文件。

  • C# 部分结束了我的永恒痛苦(复制流部分)。谢谢 (2认同)