简体   繁体   English

如何使用 Java Spring/React 下载 XLSX 文件?

[英]How to download XLSX file with Java Spring/React?

I am attempting to generate an .XLSX file and download it.我正在尝试生成一个.XLSX文件并下载它。 I am using Apache POI to generate the excel file and I am using Swagger UI to test the endpoint.我正在使用Apache POI生成 excel 文件,我正在使用Swagger UI来测试端点。 I have been searching for a few hours with little luck.我一直在寻找几个小时,但运气不佳。 The code I am using to generate my Excel file is:我用来生成 Excel 文件的代码是:

@GetMapping(path = "/download")
public ResponseEntity<ByteArrayResource> download(@RequestParam(name = "ids") long [] ids) {
    // ... other code ...
    XSSFWorkbook workbook = createWorkbook(reports);

    LocalDate date = LocalDate.now();

    String filename = "MYC " + date.getYear() + "." + date.getMonthValue();

    try {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        HttpHeaders header = new HttpHeaders();
        header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        header.set(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.xlsx", filename));
        workbook.write(stream);
        workbook.close();
        return new ResponseEntity<>(new ByteArrayResource(stream.toByteArray()), header, HttpStatus.CREATED);
    } catch (Exception e) {
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

When testing with Swagger UI , I make the call and I get this in return:使用Swagger UI进行测试时,我拨打了电话并得到了回报: 在此处输入图片说明

An answer I found on SO advised using force-download instead of vnd.openxmlformats-officedocument.spreadsheetml.sheet so I went ahead and gave it a try.我在 SO 上找到的答案建议使用force-download而不是vnd.openxmlformats-officedocument.spreadsheetml.sheet所以我继续尝试。 This time, Swagger UI was actually generating a Download file link.这一次, Swagger UI实际上生成了一个Download file链接。 I can click it and the file would download just fine.我可以点击它,文件就会下载得很好。 But is using force-download really an appropriate method?但是使用force-download真的是一种合适的方法吗?

Now, I attempted to download on my front-end and no matter if I am using force-download or vnd.openxmlformats-officedocument.spreadsheetml.sheet , I just get a 'corrupted' .xlsx file.现在,我尝试在我的前端下载,无论我是使用force-download还是vnd.openxmlformats-officedocument.spreadsheetml.sheet ,我都会得到一个“损坏”的.xlsx文件。

Just found this SO question while writing my own, and this person seems to also receive the same type of response.刚刚在写我自己的时候发现了这个SO question,这个人似乎也收到了同样类型的回复。 He fixed it by converting his binary data to string.他通过将二进制数据转换为字符串来修复它。 Not sure if that is what I should do as well and how I would go about it.不知道这是否也是我应该做的以及我将如何去做。

Okay, so I managed to figure it out by gathering information from multiple google searches.好的,所以我设法通过从多个谷歌搜索中收集信息来弄清楚。 For my backend, I encoded byte array to Base64 , then returned it as a String .对于我的后端,我将byte array编码为Base64 ,然后将其作为String返回。

@GetMapping(path = "/download")
public ResponseEntity<String> download(@RequestParam(name = "ids") long[] ids) {
    // ... other code ...
    XSSFWorkbook workbook = createWorkbook(reports);

    try {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType("text", "plain");
        workbook.write(outputStream);
        workbook.close();
        return new ResponseEntity<>(Base64.getEncoder().encodeToString(outputStream.toByteArray(), headers, HttpStatus.OK);
    } catch (IOException e) {
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

On the frontend, I decoded the String using atob() , then to ArrayBuffer在前端,我使用atob()解码String ,然后解码到ArrayBuffer

// ... other code ...
actions.getSpreadsheet(ids)
    .then(result => {
        var date = new Date();
        var filename = "JSC " +
            date.getFullYear() +
            "." +
            (date.getMonth() + 1);

        var url = window.URL.createObjectURL(new Blob([this.s2ab(atob(result.data))], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' }));
        var a = document.createElement('a');
        a.href = url;
        a.download = filename + '.xlsx';
        document.body.appendChild(a);
        a.click();
        a.remove();
    }).catch(error => {
        alert('Error retrieving report: ' + error);
    })

s2ab = s => {
    var buf = new ArrayBuffer(s.length);
    var view = new Unit8Array(buf);
    for (var i = 0; i != s.length; i++) {
        view[i] = s.charCodeAt(i) & 0xFF;
    }
    return buf;
}

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

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