【问题标题】:Downloading a file from spring rest api从 spring rest api 下载文件
【发布时间】:2019-07-05 18:39:10
【问题描述】:

我有以下 spring 控制器来下载一个文件,当我直接调用端点时它工作正常,我得到一个带有 加密内容的 csv 文件。

@GetMapping(value = "registered-cards")
    public ResponseEntity<byte[]> generateRegisteredCards(@RequestParam("from") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime from,
                                                               @RequestParam("to") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime to) throws Exception {

        byte[] bytes = cfsbReportingService.generateRegisteredCardsReport(from, to);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Access-Control-Allow-Origin", "*");
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + "report-" +  LocalDateTime.now() + ".csv");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

我的 javascript 上有以下代码来调用端点并下载文件。问题是我可以下载文件但我无法解密它,而当我通过直接调用端点下载文件时,它会被解密。

public getRegisteredCards(fromDate, toDate) : void {
        const fromEst = fromDate.startOf('day').tz('America/New_York').format();
        const endEst = toDate.endOf('day').tz('America/New_York').format();
        this.reportingService.generateNewRegisteredCardsFile(fromEst, endEst).then(
            (response:any) => {
                const blob = new Blob([response.data], {type:  'application/octet-stream'});
                const hiddenElement = document.createElement('a');
                hiddenElement.href = window.URL.createObjectURL(blob);
                hiddenElement.target = '_blank';
                hiddenElement.download = 'file.csv';
                hiddenElement.click();
            }
        ).catch(this.handleError(''));

调用服务器:

public generateNewRegisteredCardsFile(from: String, to: String) {
        const url = `${this.api()}/reporting/v1/registered-cards?from=${from}&to=${to}` ;
        const headers = new Headers({'Content-Type': 'application/octet-stream', 'Accept': 'application/octet-stream', 'Access-Control-Allow-Origin': '*'});
        return this.$http.get(url, headers);
    }        }

我在这里做错了什么?我查看了数十个示例,这就是文件的下载方式。

谢谢!

【问题讨论】:

  • 显然响应没有被正确解析。 this.reportingService 是如何进行 AJAX 调用的?
  • @RandyCasburn 是的,我正在使用 Angular httpclient,刚刚编辑了问题。
  • Angular 的 HttpClient 返回一个 Observable - 但是你使用 .then() 就好像它是一个 Promise。你确定你没有使用旧的 Http 类吗? (from @angular.http; 而不是from @angular.common.http;
  • 我对 angular 不是很熟悉,但我只用字符串内容测试了同一个调用,它可以下载正确的内容。所以我确信它不会返回一个承诺。
  • 当然。你能至少看看导入语句并告诉我我之前的哪条评论与你的导入语句匹配吗?

标签: javascript java file spring-boot download


【解决方案1】:

我最终添加了一个如下所示的 DTO 对象并将我的休息控制器更改如下:

@Data
public class RegisteredCardsReport {

    public RegisteredCardsReport(byte[] encryptedReport, String fileName) {
        this.encryptedReport = encryptedReport;
        this.fileName = fileName;
    }

    byte[] encryptedReport;
    String fileName;
}

//Rest Endpoint改变

@GetMapping(value = "new-registered-cards")
    public ResponseEntity<RegisteredCardsReport> generateNewRegisteredCards(@RequestParam("from") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime from,
                                                                                    @RequestParam("to") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime to) {

        byte[] encryptedRpt = ReportingService.generateRegisteredCardsReport(from, to);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Access-Control-Allow-Origin", "*");
        RegisteredCardsReport cardsReport = new RegisteredCardsReport(encryptedRpt, "registered-cards--" + LocalDateTime.now() + ".csv");
        return new ResponseEntity<>(cardsReport, headers, HttpStatus.OK);
    }

最后使用这篇文章中接受的答案来创建文件: Download File from Bytes in JavaScript

【讨论】:

    猜你喜欢
    • 2017-08-03
    • 1970-01-01
    • 2019-10-06
    • 2019-02-08
    • 2016-06-11
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多