Angular 前端Spring后端文件下载不工作或损坏

kknvjkwl  于 2023-03-07  发布在  Spring
关注(0)|答案(1)|浏览(124)

我有一些文件(. odt)存储在一个mysql数据库,我试图下载
Spring后端(非Spring套管):控制器:

@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;
        }
    }

Angular :组件:

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对象],有时无法在Libreoffice中打开(已损坏)
后端的byte []包含一些负数,在前端转换为正数(+256),导致其被篡改?
有人知道我哪里做错了吗?
还尝试了:Angular Spring Boot File Download

aoyhnmkz

aoyhnmkz1#

在搜索了几天之后,我想我终于找到了问题所在。在后端,我正在做的是转换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"});
        }
    }

这似乎起了作用。

相关问题