Spring + Angular - 如何下载服务器生成的文件
Spring + Angular - How to download a server generated file
我的服务器上有一个端点,它应该 return 动态生成 json 文件。这是我写的:
@GetMapping(value = "/{id}/json", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ApiOperation(value = "Animal data as a json file", authorizations = {@Authorization(value = "JWT")})
public ResponseEntity<byte[]> getAnimalFile(@PathVariable("id") String id) throws JsonProcessingException {
Animal animal = animalService.getAnimal(id);
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + animal.getId() + ".json").body(new ObjectMapper().writeValueAsBytes(animal));
}
@ApiOperation 允许 swagger 在生成我的客户端库时包含此操作。
然而,这是 ng-swagger-gen 在 Angular 端创建的:
/**
* @param id id
* @return OK
*/
getAnimalFileUsingGET(id: string): __Observable<string> {
return this.getAnimalFileUsingGETResponse(id).pipe(
__map(_r => _r.body as string)
);
}
这不太理想,因为我无法通过这种方式下载服务器生成的文件。在我的组件中,我有一个 exportJSON 方法:
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe(content => {
console.log(content); // prints the json content but I don't have the filename
});
}
我在 SO 上查看了其他答案,他们说使用 window.open(SERVER_ENDPOINT_HERE)
但这不起作用,因为我的端点使用身份验证 (JWT)。
有没有办法:
- 让 ng-swagger-gen 意识到这是一个带有文件名的文件,并在我订阅 Observable 时向我提供两者 returns
- 或绕过 swagger 并使用 Angular 使用服务器提供的文件名和身份验证下载文件?
理想的解决方案是更改服务器端的某些内容,以便 swagger 生成正确的响应类型,以便我可以从服务器获取文件和文件名。
尝试以下操作:
getAnimalFileUsingGET(id: string | number): Observable<Blob> {
return this.http.get(`/stats/export/${id}`, {responseType: 'blob'}); // Adjust your GET accordingly
}
此外,您还需要安装 FileSaver.js
npm i file-saver@1.3.2
最后,像这样使用它:
import { saveAs } from 'file-saver';
.
.
.
.
.
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe((blob: Blob) => {
saveAs(blob, 'export.json');
});
}
编辑 1:
为了能够访问 Content-disposition
header,您需要指示 Angular Http 客户端在响应中做一些更改。
getAnimalFileUsingGET(id: string | number): Observable<HttpResponse<any>> {
return this.http.get(`/stats/export/${id}`, {observe: 'response', responseType: 'json' })
}
那么您可以这样订阅:
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe((resp: HttpResponse<Blob>) => {
console.log(resp.headers.get('content-disposition'));
// Extract filename from header
const filename = '';
saveAs(resp.body, filename);
});
}
我的服务器上有一个端点,它应该 return 动态生成 json 文件。这是我写的:
@GetMapping(value = "/{id}/json", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ApiOperation(value = "Animal data as a json file", authorizations = {@Authorization(value = "JWT")})
public ResponseEntity<byte[]> getAnimalFile(@PathVariable("id") String id) throws JsonProcessingException {
Animal animal = animalService.getAnimal(id);
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + animal.getId() + ".json").body(new ObjectMapper().writeValueAsBytes(animal));
}
@ApiOperation 允许 swagger 在生成我的客户端库时包含此操作。 然而,这是 ng-swagger-gen 在 Angular 端创建的:
/**
* @param id id
* @return OK
*/
getAnimalFileUsingGET(id: string): __Observable<string> {
return this.getAnimalFileUsingGETResponse(id).pipe(
__map(_r => _r.body as string)
);
}
这不太理想,因为我无法通过这种方式下载服务器生成的文件。在我的组件中,我有一个 exportJSON 方法:
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe(content => {
console.log(content); // prints the json content but I don't have the filename
});
}
我在 SO 上查看了其他答案,他们说使用 window.open(SERVER_ENDPOINT_HERE)
但这不起作用,因为我的端点使用身份验证 (JWT)。
有没有办法:
- 让 ng-swagger-gen 意识到这是一个带有文件名的文件,并在我订阅 Observable 时向我提供两者 returns
- 或绕过 swagger 并使用 Angular 使用服务器提供的文件名和身份验证下载文件?
理想的解决方案是更改服务器端的某些内容,以便 swagger 生成正确的响应类型,以便我可以从服务器获取文件和文件名。
尝试以下操作:
getAnimalFileUsingGET(id: string | number): Observable<Blob> {
return this.http.get(`/stats/export/${id}`, {responseType: 'blob'}); // Adjust your GET accordingly
}
此外,您还需要安装 FileSaver.js
npm i file-saver@1.3.2
最后,像这样使用它:
import { saveAs } from 'file-saver';
.
.
.
.
.
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe((blob: Blob) => {
saveAs(blob, 'export.json');
});
}
编辑 1:
为了能够访问 Content-disposition
header,您需要指示 Angular Http 客户端在响应中做一些更改。
getAnimalFileUsingGET(id: string | number): Observable<HttpResponse<any>> {
return this.http.get(`/stats/export/${id}`, {observe: 'response', responseType: 'json' })
}
那么您可以这样订阅:
exportJSON(): void {
this.animalService.getAnimalFileUsingGET(this.animal.id).subscribe((resp: HttpResponse<Blob>) => {
console.log(resp.headers.get('content-disposition'));
// Extract filename from header
const filename = '';
saveAs(resp.body, filename);
});
}