使用Angular下载zip文件

13

我已经花了好几个小时,试图通过 Angular 下载一个 zip 文件。 下载的文件比原文件要小。我按照这个链接 How do I download a file with Angular2 的方法进行操作。

出于认证原因,我不能只使用<a>标签进行下载。

服务

 downloadfile(filePath: string){
        return this.http
            .get( URL_API_REST + 'downloadMaj?filePath='+ filePath)
            .map(res => new Blob([res], {type: 'application/zip'}))
    }
downloadfileComponent(filePath: string){
        this.appService.downloadfile(filePath)
            .subscribe(data => this.getZipFile(data)),
                error => console.log("Error downloading the file."),
                () => console.log('Completed file download.');
    }


getZipFile(data: any){
        var a: any = document.createElement("a");
        document.body.appendChild(a);

        a.style = "display: none";
        var blob = new Blob([data], { type: 'application/zip' });

        var url= window.URL.createObjectURL(blob);

        a.href = url;
        a.download = "test.zip";
        a.click();
        window.URL.revokeObjectURL(url);

    }

REST API

public void downloadMaj(@RequestParam(value = "filePath") String filePath, HttpServletResponse response) {

        System.out.println("downloadMaj");
        File fichierZip = new File(filePath);

        try {
            System.out.println("nom du fichier:" + fichierZip.getName());
            InputStream inputStream = new FileInputStream(fichierZip);

            response.addHeader("Content-Disposition", "attachment; filename="+fichierZip.getName());
            response.setHeader("Content-Type", "application/octet-stream");

            org.apache.commons.io.IOUtils.copy(inputStream, response.getOutputStream());
            response.getOutputStream().flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

有人可以解释一下为什么没有下载完整个文件吗?

已解决

downloadfile(filePath: string) {
        return this.http
          .get( URL_API_REST + 'download?filePath=' + filePath, {responseType: ResponseContentType.ArrayBuffer})
          .map(res =>  res)
      }
private getZipFile(data: any) {
    const blob = new Blob([data['_body']], { type: 'application/zip' });

    const a: any = document.createElement('a');
    document.body.appendChild(a);

    a.style = 'display: none';    
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = test.zip;
    a.click();
    window.URL.revokeObjectURL(url);

  }

请在您的最后一个区块中添加 "test.zip"(需要双引号)。 - undefined
4个回答

25
  1. 在 responseType 中,你需要分配一个字符串,例如 arraybufferAngular 5+)。

downloadFile(filename: string) {
  return this.http.get(URL_API_REST + 'download?filename=' + filename, {
    responseType: 'arraybuffer'
  });
}

  1. 我们可以使用以下代码直接下载我们的文件:

this.myService.downloadFile(filename).subscribe(data => {
  const blob = new Blob([data], {
    type: 'application/zip'
  });
  const url = window.URL.createObjectURL(blob);
  window.open(url);
});


4
请告诉我如何指定下载的 zip 文件的名称? - Himanshu
我收到了“Type {} is not assignable to BlobPart”的错误,我认为返回类型arraybuffer无法分配给Blob。 - Naga

2

使用angular实现zip文件下载需要多个插件:

  1. angular-file-saver.bundle

    该插件会打包Blob.js和FileSaver.js,请遵循所有指示,只需在控制器和模块上添加依赖即可。

    .module('fileSaverExample', ['ngFileSaver']) .controller('ExampleCtrl', ['FileSaver', 'Blob', ExampleCtrl]);

  2. 添加JSZipJSZipUtils

需要包含的文件有:jszip.js, jszip-utils.js, angular-file-saver.bundle.js

var zip = new JSZip();
zip.file("Hello.txt", "Hello World\n");

// when everything has been downloaded, we can trigger the dl
zip.generateAsync({type:"blob"}).then(function (blob) { // 1) generate the zip file
FileSaver.saveAs(blob, "downloadables.zip");                          // 2) trigger the download
}, function (err) {
    console.log('err: '+ err);
});


我编辑了问题,解释了如何在不使用任何插件的情况下解决问题。 - edkeveked
我们如何在单个zip文件中下载多个文件? - ResolveError

1
在Angular中,无需使用jsZip-util,您可以通过带有标头选项的服务调用来完成。
public zipAndDownload(url): Observable<any> {
       const options:any = {
        headers: new HttpHeaders({'Content-Type': 'file type of an particular document'}),
        withCredentials: true,
        responseType:'arraybuffer'
      }; 
        return this.http.get<Content>(url,options);

      }

0

我使用FileSaver在本地机器上保存文件。它可以接受blob或字符串数据,并使用给定/默认名称保存文件。来自官方文档:

function FileSaver.saveAs(data: string | Blob, filename?: string, options?: FileSaver.FileSaverOptions): void

Download.Service.ts

downloadFile() {
    return this.http.get(url, { params, responseType: 'arraybuffer', observe: 'response' }).pipe(
        map(res => res)
    );
}

my.component.ts

this.downloadService.downloadFile().subscribe((response: HttpResponse<any>) => {
    if(response.body) {
        let fileName = "download.zip";
        const cDisposition: string = response.headers.get('content-disposition');
        if (cDisposition && cDisposition.indexOf(';filename=') > -1) {
            fileName = cDisposition.split(';filename=')[1];
        }

        const data = new Blob([new Uint8Array(response.body)], {
            type: 'application/octet-stream'
        });
        FileSaver.saveAs(data, fileName);
    }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接