如何在Angular 4中下载Excel/Zip文件

6

我正在使用Angular 4作为前端,Lumen 5.4作为后端。

我的需求是将一些数据导出为Excel和Zip文件。

使用'file-saver/FileSaver'包中的{ saveAs }进行文件下载。

Angular 4代码:

downloadExcel() {

const type = 'application/vnd.ms-excel';
const headers = { headers: new Headers({ 'Accept': type }) };
const filename = 'file.xls';

this.http.get('http://10.2.2.109/Download/exportExcel', headers)
  .toPromise()
  .then(response => this.saveToFileSystem(response, type, filename));

return false;


}



private saveToFileSystem(response, __type, filename) {
    const contentDispositionHeader: string = response.headers.get('Content-Disposition');

if (contentDispositionHeader !== null) {
  const parts: string[] = contentDispositionHeader.split(';');
  //const filename = parts[1].split('=')[1];
  const blob = new Blob([response._body], { type: __type });
  saveAs(blob, filename);
} else {
  alert('Cant download.....');
  // handling download condition if content disposition is empty
  const blob = new Blob([response._body], { type: __type });
  saveAs(blob, filename);
}


}

Lumen 代码

public function exportExcel(Request $request) {
        $file = storage_path();
        $file_name = 'book1.xls';
        $headers = [
            'Content-type' => 'application/vnd.ms-excel',
            'Content-Disposition' => 'attachment;filename="' . $file_name,
            'X-Filename' => $file_name,
            'Content-Transfer-Encoding' => 'binary',
            'Content-Length' => filesize($file . '/' . $file_name),
            'Cache-Control' => 'max-age=0',
            'Cache-Control' => 'max-age=1',
            'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
            'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
            'Cache-Control' => 'cache, must-revalidate',
            'Pragma' => 'public',
            'Set-Cookie' => 'fileDownload=true; path=/',
            'Access-Control-Expose-Headers' => 'Content-Length,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma'
        ];

        return response()->download($file . '/' . $file_name, $file_name, $headers);
    }

问题

  1. const contentDispositionHeader: string = response.headers.get('Content-Disposition'); 看起来总是为空。
  2. 我们无法打开下载的文件,显示损坏的消息。
  3. 它可以用于文本文件下载。

请帮助我解决这个问题。或者指定任何其他适用于angular的可行代码/包。

2个回答

10

试试这个:

downloadExcel() {

  const type = 'application/vnd.ms-excel';
  const filename = 'file.xls';
  const options = new RequestOptions({
            responseType: ResponseContentType.Blob,
            headers: new Headers({ 'Accept': type })
        });

  this.http.get('http://10.2.2.109/Download/exportExcel', options)
           .catch(errorResponse => Observable.throw(errorResponse.json()))
           .map((response) => { 
                 if (response instanceof Response) {
                    return response.blob();
                 }
                 return response;
            })
           .subscribe(data => saveAs(data, filename),
                      error => console.log(error)); // implement your error handling here

}

关键点在于 RequestOptions 上的 responseType: ResponseContentType.Blob 和获取响应时使用 response.blob()

一般来说,不建议像这样访问响应的 _body 属性:response._body,而是应该调用相应的方法根据类型获取正文内容(例如 response.blob()response.json() 等)。


还有一个疑问,如何修改服务以访问JSON数据和Blob数据。条件是我们在请求中传递授权标头,如果授权失败或无法生成Excel API,则API将返回JSON。在这种情况下,我们如何更改服务以访问响应类型以处理Blob和JSON数据。 - Binish Prabhakar
请查看我的更新代码示例,可能会有一个解决方案。我添加了一个catch操作符,它将捕获任何HTTP错误响应(因此基本上是HTTP错误代码> 400),然后从响应中提取json,创建一个新的Observable并传递该内容。然后,在map中,您必须检查输入是否是Response的实例以提取blob(快乐情况),或者如果不是,则只需传递内容(错误情况)。请注意,这未经测试,因此我不确定它是否有效。但是,至少它应该给你一些想法 :) - Andrei Matracaru
好的,你不应该 :). 你应该使用HTTP状态码来表示错误条件,例如401表示未授权或400表示错误请求。否则,我真的看不出你如何区分成功响应和错误。我猜你可以尝试在map函数中使用response.blob(),然后在catch块中使用response.json()...但这相当丑陋。 - Andrei Matracaru
由于我刚接触Angular,请给我建议,针对上述场景,最佳的编写代码方法是什么? - Binish Prabhakar
如何捕获错误消息。如果HTTP状态不是200。现在我们正在使用catch和subscribe响应,无法获取响应正文。只能获取错误。Statustext - Binish Prabhakar
显示剩余2条评论

0

如果输入数据是JSON格式的,您可以使用 json2csv。该函数的输出将为CSV格式,可在Microsoft Excel或Google Sheets中打开。

安装软件包:

$ npm install json2csv --save

将以下内容添加到您的组件中:
var json2csv = require('json2csv');
var fields = ['field1', 'field2', 'field3'];
var result = json2csv({ data: myData, fields: fields });

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