这里我有下面这样的动态数据
data = [
"https://dummyimage.com/200x200/000/fff.jpg&text=test",
"https://dummyimage.com/200x200/000/fff.jpg&text=testOne",
"https://dummyimage.com/200x200/000/fff.png&text=testTwo"
]
在按钮上单击我想从这些URL中获取所有图像并将其保存为zip
问题:每当我能够以zip格式下载文件并尝试将其解压缩时,由于无法打开image.zip作为存档,我将收到错误消息;如果我另存为单个图像,则该图像也不会打开并且存在任何方式存储
下面是我的代码
downloadImageData(){
var blob = new Blob([this.data], { type: 'application/zip'' });
FileSaver.saveAs(blob,'image.zip');
}
在这里,我同时拥有png和jpg以及各种类型的数据,因此链接获得的所有数据都必须以zip文件格式下载,因此对于角度5+来说,有什么方法可以解决。我也在使用filesave angular package
JS ZIP _body响应
通过使用http模块im获取以下数据[
{
"_body": {
},
"status": 200,
"ok": true,
"statusText": "OK",
"headers": {
"date": [
"Sun",
" 25 Nov 2018 12:18:47 GMT"
],
"cache-control": [
"public",
" max-age=43200"
],
"expires": [
"Mon",
" 26 Nov 2018 00:18:47 GMT"
],
"content-disposition": [
"attachment; filename=2B.JPG"
],
"content-length": [
"40649"
],
"server": [
"Werkzeug/0.14.1 Python/2.7.13"
],
"content-type": [
"image/jpg"
]
},
"type": 2,
"url": "http://some url"
}
]
答案 0 :(得分:2)
我已经创建了一个演示应用程序here。
P.S:该代码仅供参考,可能不包括标准的编码做法,但可以指导您创建自己的解决方案版本。
我正在使用jszip来压缩文件。
app.module.ts :
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import * as JSZip from 'jszip';
import { saveAs } from 'file-saver';
@NgModule({
imports: [ BrowserModule, HttpClientModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
app.component.ts:
import { OnInit, Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as JSZip from 'jszip';
import { saveAs } from 'file-saver';
@Component({
selector: 'my-app',
template: `<button (click)='downloadZip()'>Download</button>`
})
export class AppComponent {
constructor(private http: HttpClient) {
}
downloadZip() {
this.loadSvgData("https://c.staticblitz.com/assets/client/icons/file-icons/angular-component-31179578a9a8a16512e9e90ade26549a.svg",
this.saveAsZip);
}
private loadSvgData(url: string, callback: Function) : void{
this.http.get(url, { responseType: "arraybuffer" })
.subscribe(x => callback(x));
}
private saveAsZip(content: Blob) : void{
var zip = new JSZip.default();
zip.file("image.svg", content);
zip.generateAsync({ type: "blob" })
.then(blob => saveAs(blob,'image.zip'));
};
}
说明:
该应用程序只有一个按钮,单击该按钮将使用HttpClient
从服务器下载图像文件。它将使用jszip
压缩下载的数据,并使用file-saver
将其保存到浏览器。
我希望这会有所帮助!
答案 1 :(得分:2)
我来晚了,但是这段代码将使用您的图像数组并创建GET请求。之后,它将执行所有请求,并将响应添加到您的zip文件中,然后下载。
如果您不喜欢使用fileSaver,我提供了两种下载文件的方法。选择您喜欢的任何一个。
编辑:
如果您使用的是旧版本的rxjs,则必须以其他方式导入forkJoin
,请查阅rxjs文档。
另外,请确保您的后端允许下载文件,否则会出现CORS错误。
app.component.ts
import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { forkJoin } from "rxjs";
import { saveAs } from "file-saver";
import * as JSZip from 'jszip';
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
data = [
'http://yoururl/file.png',
'http://yoururl/file2.png'
];
getRequests = [];
constructor(private _http: HttpClient) {}
download() {
this.createGetRequets(this.data);
forkJoin(...this.getRequests)
.subscribe((res) => {
const zip = new JSZip();
res.forEach((f, i) => {
zip.file(`image${i}.png`, f);
});
/* With file saver */
// zip
// .generateAsync({ type: 'blob' })
// .then(blob => saveAs(blob, 'image.zip'));
/* Without file saver */
zip
.generateAsync({ type: 'blob' })
.then(blob => {
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 = 'image.zip';
a.click();
window.URL.revokeObjectURL(url);
});
});
}
private createGetRequets(data: string[]) {
data.forEach(url => this.getRequests.push(this._http.get(url, { responseType: 'blob' })));
}
}
app.component.html
<div style="text-align:center">
<button (click)="download()">Download</button>
</div>
我还必须在tsconfig.json中包含jszip的路径。根据您的Angle版本,您不必执行此操作。在"compilerOptions"
内添加以下内容:
tsconfig.json
"paths": {
"jszip": [
"node_modules/jszip/dist/jszip.min.js"
]
}
更新:
这是旧的HttpModule的解决方案,我尝试了一下,它可以工作。我建议尽可能更改为新的HttpClientModule。
UPDATE2:
就像我在评论中所说,保存文件以处理不同的文件类型时,可以更改文件扩展名。这是一个示例,您可以轻松扩展此解决方案。
app.component.ts
import { Component } from "@angular/core";
import { Http, ResponseContentType } from "@angular/http"; // Different Import
import { forkJoin } from "rxjs";
import { saveAs } from "file-saver";
import * as JSZip from "jszip";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
/*
UPDATE 2
Create a Type map to handle differnet file types
*/
readonly MIME_TYPE_MAP = {
"image/png": "png",
"image/jpeg": "jpg",
"image/jpg": "jpg",
"image/gif": "gif"
};
data = [
"http://url/file.png",
"http://url/file.jpeg",
"http://url/file.gif"
];
getRequests = [];
constructor(private _http: Http) {} // Different Constructor
download() {
this.createGetRequets(this.data);
forkJoin(...this.getRequests).subscribe(res => {
const zip = new JSZip();
console.log(res);
/*
The return value is different when using the HttpModule.
Now you need do access the body of the response with ._body,
as you can see inside the forEach loop => f._body
*/
let fileExt: String; // UPDATE 2
res.forEach((f, i) => {
fileExt = this.MIME_TYPE_MAP[f._body.type]; // UPDATE 2, retrieve type from the response.
zip.file(`image${i}.${fileExt}`, f._body); // UPDATE 2, append the file extension when saving
});
zip
.generateAsync({ type: "blob" })
.then(blob => saveAs(blob, "image.zip"));
});
}
private createGetRequets(data: string[]) {
/*
Change your responseType to ResponseContentType.Blob
*/
data.forEach(url =>
this.getRequests.push(
this._http.get(url, { responseType: ResponseContentType.Blob })
)
);
}
}
UPDATE3:
从URL提取文件名的解决方案,因此不需要文件类型:
import { Component } from "@angular/core";
import { Http, ResponseContentType } from "@angular/http";
import { forkJoin } from "rxjs";
import { saveAs } from "file-saver";
import * as JSZip from "jszip";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
data = ["http://url/file.png", "http://url/file.jpg", "http://url/file.gif"];
getRequests = [];
constructor(private _http: Http) {}
download() {
this.createGetRequets(this.data);
forkJoin(...this.getRequests).subscribe(res => {
const zip = new JSZip();
let fileName: String;
res.forEach((f, i) => {
fileName = f.url.substring(f.url.lastIndexOf("/") + 1); // extract filename from the response
zip.file(`${fileName}`, f._body); // use it as name, this way we don't need the file type anymore
});
zip
.generateAsync({ type: "blob" })
.then(blob => saveAs(blob, "image.zip"));
});
}
private createGetRequets(data: string[]) {
data.forEach(url =>
this.getRequests.push(
this._http.get(url, { responseType: ResponseContentType.Blob })
)
);
}
}