繁体   English   中英

使用reactJS下载xlsx文件:Excel无法打开文件

[英]Download an xlsx file with reactJS: Excel can not open file

我正在尝试使用reactJS下载xlsx文件,但是在下载后尝试打开文件时收到此消息:

“ Excel无法打开文件'file.xlsx',因为文件格式或文件扩展名无效。请验证文件未损坏且文件扩展名与文件格式匹配”

这是前端代码:

const REST_DOWNLOAD_URL = REST_URL + '/token';

Rest.ajaxPromise('GET', REST_DOWNLOAD_URL).then(function (res) {

var FILE_URL = "/supermarket/token/" + res;
Rest.ajaxPromise('GET', FILE_URL).then(function (my_file) {


                let blob = new Blob([my_file._body], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' });

                if (navigator.msSaveOrOpenBlob) {
                    navigator.msSaveBlob(blob, 'file.xlsx');
                } else {

                    let link = document.createElement('a');
                    link.href = window.URL.createObjectURL(blob);
                    link.setAttribute('download', 'file.xlsx');
                    document.body.appendChild(link);
                    link.download = '';
                    link.click();
                    document.body.removeChild(link);

                }
            });

});

为什么会出现此错误? 请有人帮我,我坚持了三个星期

[编辑1]

我要下载的文件建立在后端,基本上我在数据库上获取值并使用Apache poi工作簿创建excel工作表。 我将向您展示代码的主要部分:

1)该方法在前端的第一个GET请求中由前端调用,目的是在下载之前准备文件。 非常简单,只需创建一个令牌(buildToken())并将一个临时文件与此令牌(createTempFile(randomBackendToken))关联。 临时文件充满了我在数据库中得到的内容(createFile(os))

@RequestMapping(value = "/token", method = RequestMethod.GET)
public String returnToken() throws IOException {

        String randomBackendToken = tokenGenerator.buildToken();
        OutputStream os = tokenGenerator.createTempFile(randomBackendToken);
        tokenGenerator.createFile(os);

        return randomBackendToken;

    }

2)我创建临时文件的方法:

public OutputStream createTempFile(String randomBackendToken) throws IOException {

        OutputStream os = null;
        File file = File.createTempFile(randomBackendToken, ".xlsx"); 
        os = new FileOutputStream(file); 

        return os;
    }

3)我收到空的临时文件并用数据库中的数据填充的方法:

public void createFile(OutputStream os) throws IOException {

        List<Supermakets> supermarkets = service.findAllSupermarkets(); 
        Workbook workbook = writeExcel.createSheet(supermarkets); 
        workbook.write(os); 
        IOUtils.closeQuietly(os);
}

4)构建xlsx文件的我的WriteExcel类:

private static String[] columns = {"Code", "Name", "Type"};

    public Workbook createSheet(List<Supermarket> supermarkets) throws IOException {

        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("file");

        [....]

        // Row for Header
        Row headerRow = sheet.createRow(0);

        // Header
        for (int col = 0; col < columns.length; col++) {
            Cell cell = headerRow.createCell(col);
            cell.setCellValue(columns[col]);
            cell.setCellStyle(headerCellStyle);
        }

        //Content
        int rowIdx = 1;
        for (Supermarket supermarket : supermarkets) {
            Row row = sheet.createRow(rowIdx++);

            row.createCell(0).setCellValue(supermarket.getCode());
            row.createCell(1).setCellValue(supermarket.getName());
            row.createCell(2).setCellValue(supermarket.getType());

        }
        return workbook;

}

因此,以上所有内容仅用于第一个GET申请。 我再做一个,下面的方法保存第二个申请。 我只验证前端返回给我和他们的令牌,基于验证,我允许下载我在上一步中创建的文件:

public void export(@PathVariable(value = "frontendToken") String frontendToken, HttpServletResponse response) throws IOException {

        if (StringUtils.isNotBlank(frontendToken)) {

            String tmpdir = System.getProperty("java.io.tmpdir");


            File folder = new File(tmpdir);
            File[] listOfFiles = folder.listFiles();


            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    boolean fileIsValid = tokenGenerator.validateToken(frontendToken, listOfFiles[i]);

                    if (fileIsValid) {

                        InputStream input = new FileInputStream(listOfFiles[i]);
                        OutputStream output = response.getOutputStream();

                        int data = input.read();

                        while (data != -1) {

                            output.write(data);
                            data = input.read();

                        }
                        input.close();
                        output.flush();
                        output.close();

                        String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                        response.setContentType(mimeType);

                        listOfFiles[i].delete(); 
                    }
                }
            }
        }
    }

这就是我正在做的所有事情。 找不到什么问题或我所缺少的。 当我在导航器上按F12键查看请求的响应时,会为我显示一些编码的内容,例如:

PK@SM_rels/.rels­’ÁjÃ0†_ÅèÞ8í`ŒQ·—2èmŒî4[ILbËØÚ–½ýÌ.[Kì($}ÿÒv?‡I½Q.ž£uÓ‚¢hÙùØx>=¬î@ÁèpâH"Ã~·}¢

有什么怀疑吗?

伙计们!

问题是:我的二进制数据被javascript转换为字符串,这破坏了我的excel文件。 我解决了将后端的二进制数据转换为文本,然后在前端进行逆转换的问题。 以下链接对我有帮助:

java将inputStream转换为base64字符串

在JavaScript中从base64字符串创建Blob

谢谢所有尝试提供帮助的人。 我希望我的问题可以帮助其他人

暂无
暂无

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

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