Download an xlsx file with reactJS: Excel can not open file

12,354

guys!

The problem was: my binary data was being converted for string by javascript and this was breaking my excel file. i solved my problem converting my binary data on backend to text and then on frontend i make the inverse. The following links helped me:

java convert inputStream to base64 string

Creating a Blob from a base64 string in JavaScript

Thank you for everyone that tried to help. I hope my question can help others

Share:
12,354
thomas
Author by

thomas

Updated on June 04, 2022

Comments

  • thomas
    thomas almost 2 years

    I'm trying to download an xlsx file with reactJS but i'm receiving this message when i try to open my file after download:

    "Excel can not open file 'file.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the file format"

    Here's the frontend code:

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

    Why am i getting this error? Please somebody help me, i'm stuck on this for 3 weeks

    [EDIT 1]

    The file that i'm trying to download is build on backend, basically i get the values on database and use the Apache poi workbook to create the excel sheet. I will show you the mainly parts of the code:

    1) This method is called by frontend on the first GET requisition of frontend and aims to prepare the file before the download. Is very simple, just create a token (buildToken()) and associate a temp file with this token (createTempFile(randomBackendToken)). The temp file is filled with what i get on my database (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) The method where i create the temp file:

    public OutputStream createTempFile(String randomBackendToken) throws IOException {
    
            OutputStream os = null;
            File file = File.createTempFile(randomBackendToken, ".xlsx"); 
            os = new FileOutputStream(file); 
    
            return os;
        }
    

    3) The method where i receive the empty temp file and fills with my data on database:

    public void createFile(OutputStream os) throws IOException {
    
            List<Supermakets> supermarkets = service.findAllSupermarkets(); 
            Workbook workbook = writeExcel.createSheet(supermarkets); 
            workbook.write(os); 
            IOUtils.closeQuietly(os);
    }
    

    4) My WriteExcel Class that build the xlsx file:

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

    So, this all above is just for the first GET requisition. I make another one and the method below holds the second requisition. I just verify the token that the frontend returns for me and them, based on the validation, i allow the download of the file that i created on the previous step:

    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(); 
                        }
                    }
                }
            }
        }
    

    And that's all that i'm doing. Can't find what's wrong or what i'm missing. When i press F12 on my navigator to see the response of the request, shows for me something encoded, like:

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

    Any suspicions of what can be?

    • SLaks
      SLaks over 5 years
      Are you sure your file bytes are actually xlsx?
    • thomas
      thomas over 5 years
      The file that i'm trying to download is build on backend, basically i get the values on database and use the Apache poi workbook to create the excel sheet. I added details of my backend on my question above