我有一些文件 (.odt) 存储在我尝试下载的 mysql 数据库中
Spring 后端(不是 Spring boot): 控制器:
@RequestMapping(value = "/downloadRequest", method = RequestMethod.GET)
public ResponseEntity<Resource> downloadRequest(@RequestParam(value="id") int id) throws JsonProcessingException {
try {
byte [] fileData = getDocumentRestService().downloadRequest(id);
Resource inputStreamResource = new InputStreamResource(new ByteArrayInputStream(fileData));
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(fileData.length);
headers.set(HttpHeaders.CONTENT_TYPE, "application/vnd.oasis.opendocument.text");
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"" + inputStreamResource.getFilename() + "\"");
ResponseEntity<Resource> responseEntity = ResponseEntity.ok().headers(headers).body(inputStreamResource);
return responseEntity;
} catch (Exception e) {
return null;
}
}
角度: 成分:
download() {
let id: number = this.documentDetailFormGroup.controls['id'].value;
if(id > 0) {
this.documentDatasource.downloadFormData(id).subscribe(data => {
let fileData = [];
fileData.push(data.body);
let downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(new Blob(data, { type: 'application/vnd.oasis.opendocument.text' }));
downloadLink.download = "Test.odt";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
}
}
通用数据源:
downloadFormData(id: number): Observable<any> {
return this.ssBaseRequestService.sendDownloadRequestWithParams("GET", this.requestMapping + "/downloadRequest", this.ssBaseRequestService.httpParams(id));
}
请求服务:
public sendDownloadRequestWithParams(method: string, url: string, params?: HttpParams): Observable<any> {
return this.httpClient.get(this.backend_url + url, {params: params, observe: 'response', responseType: 'blob'});
}
对于 Spring,我已经尝试使用 Jackson 返回 byte[]、Response 和 json 响应:
// console.log(data.dto.fileData);
// var buf = Buffer.from(data.dto.fileData, 'base64').toString('utf8');
// console.log(buf);
// //console.log(atob(data.dto.fileData));
// let fileData = [];
// // let fileData = new Blob(atob(data.dto.fileData), { type: data.dto.contentType });
// fileData.push(buf);
// // console.log(fileData);
对于 Angular 我也尝试返回:
Observable<Blob>
似乎没有任何效果。
.odt 文件为空或 .odt 文件包含 [Object object],有时无法在 Libreoffice 中打开(已损坏)
后端的byte[]包含一些负数,在前端被转换为正数(+256),导致被破坏?
有人知道我做错了什么吗?
还尝试过: Angular Spring Boot 文件下载
找了几天我想我终于找到了问题所在。 在后端,我正在做的是转换 blob:
public static byte[] convertBlobToBytes(Blob blob) {
if(blob == null) {
throw new ServiceException("exists.not", new String[] {"file"});
}
try {
StringWriter stringWriter = new StringWriter();
IOUtils.copy(blob.getBinaryStream(), stringWriter, Encoding.UTF_8);
return stringWriter.toString().getBytes();
} catch (SQLException e) {
throw new ServiceException("exists.not", new String[] {"file"});
} catch (IOException e) {
throw new ServiceException("filecopy.failed");
}
}
我将其替换为:
public static byte[] convertBlobToBytes1(Blob blob) {
if(blob == null) {
throw new ServiceException("exists.not", new String[] {"file"});
}
try {
return blob.getBytes(1, (int)blob.length());
} catch (SQLException e) {
throw new ServiceException("exists.not", new String[] {"file"});
}
}
这似乎可以解决问题。