简体   繁体   English

如何通过 ResponseEntity 发送 ByteArrayResource

[英]How to send a ByteArrayResource via ResponseEntity

I am working on a Java application, and the functionality I am working on is to download a file after populating it's content from the database when the user clicks on export button, the file is generated correctly, the problem I have is when I try to set ByteArrayResource into the ResponseEntity , when I call the webservice from angular, I get Byte array resource [resource loaded from byte array] cannot be resolved to absolute file path , here is my code:我正在开发 Java 应用程序,我正在处理的功能是在用户单击导出按钮时从数据库中填充文件内容后下载文件,文件生成正确,我遇到的问题是当我尝试将ByteArrayResource设置为ResponseEntity ,当我从 angular 调用 web 服务时,我得到Byte array resource [resource loaded from byte array] cannot be resolve to absolute file path ,这是我的代码:

Controller method: Controller 方法:

  @GetMapping(value = "/exportods/{id}")
  public ResponseEntity<ExportDTO> exportODSFile(@PathVariable  String id)
      throws InvalidationRequestNotFoundException, IOException, ExportInvalidationRequestException {


    File odsFfile = null;
    ByteArrayResource resource = null;
    ExportInvalidationRequestDTO exportInvalidationRequestDTO = new ExportInvalidationRequestDTO();
    try {

      //getting the file
      odsFfile = exportService.exportInvalidationRequest(id);

      Path pathObj = Paths.get(odsFfile.getCanonicalPath());

      //creating the resource
      resource = new ByteArrayResource(Files.readAllBytes(pathObj));

      exportDTO.setResource(resource);

    } catch (IOException e) {
      exportDTO.setError(new ErrorDTO(HttpStatus.NOT_FOUND.value()));
    }

    return ResponseEntity.ok(exportDTO);
  }

ExportDTO:出口DTO:

public class ExportDTO extends AbstractReturnDTO {
  private ByteArrayResource resource;

  public ExportDTO (ByteArrayResource resource) {
    this.resource = resource;
  }

  public ExportDTO () {
  }

  public ByteArrayResource getResource() {
    return resource;
  }

  public void setResource(ByteArrayResource resource) {
    this.resource = resource;
  }
}

Angular component method: Angular组件方法:

async downloadODSFile(id) {
    await this.requestService.downloadODSFile(id).subscribe((requestExportODS: RequestExportODS) => {
        if (!requestExportODS) {
            if(requestExportODS.error == null){
                //handle error here
            }
           else{
                saveAs(new Blob([requestExportODS.file], { type: \'application/vnd.oasis.opendocument.spreadsheet\'' }), id );
            }
        }
    });
}

Once I click on the export button, I get an error:单击导出按钮后,出现错误:

error: "Internal Server Error"
message: "Byte array resource [resource loaded from byte array] cannot be resolved to absolute file path"

Set the observe as response in the http service method在 http 服务方法中将observe设置为response

//requestService
downloadODSFile(id) {
 return this.http.get<HttpResponse<any>>(`/exportods/${id}`, { observe: 'response' })
}

And use it like this并像这样使用它

async downloadODSFile(id) {
    await this.requestService.downloadODSFile(id).subscribe(res => {
        console.log(res.body) //Byte array
    });
}

BTW async and await are redundant in your code, as you haven't converted observable to promise. BTW async 和 await 在您的代码中是多余的,因为您尚未将 observable 转换为 promise。

You should return a InputStreamResource directly and let the browser download the file.您应该直接返回InputStreamResource并让浏览器下载文件。 Ie build the request url and put it into an <a> tag and let the user click on it.即构建请求 url 并将其放入<a>标记并让用户单击它。 Additionally you can set the filename via headers:此外,您可以通过标题设置文件名:

    final InputStream inputStream = new FileInputStream(filePath);

    return ResponseEntity.ok()
            .header("Content-Disposition", "attachment; filename=" + fileName)
            .body(new InputStreamResource(inputStream));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM