The Excel document became corrupted after downloading through a ReactJs jQuery ajax post request

Attempting to download a file using jQuery AJAX post request from ReactJs, with an express router middleware layer utilizing the Request API to send requests to a Spring Boot REST API. The flow goes like this: AJAX => Express POST route => Spring Boot API. However, every time the file downloads, its content appears corrupted.

Despite trying various solutions found online, none have seemed to work in resolving the issue.

// jQuery AJAX calling the Express POST route
$.ajax({
            url: "/downloadReport",
            contentType: 'application/json',
            data:JSON.stringify({"data1":"value1"}),
            type:'POST',
            cache: true,
            responseType: 'arraybuffer',
            success: function(response) {
                console.log(response);
                var fileName=response.headers['content-disposition'].split('filename=')[1];
                var blob = new Blob([response.data], {type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
                const blobURL = window.URL.createObjectURL(blob);
                const tempLink = document.createElement('a');
                tempLink.style.display = 'none';
                tempLink.href = blobURL;
                tempLink.setAttribute('download', fileName);
                tempLink.click();

            }.bind(this),
            error: function(xhr, status, err) {
                console.log(err)
                console.log(status)
                console.log(xhr)
            }.bind(this)
        })

// Express route
router.post("/downloadReport", (req, response, next) => {
    request(
        {
            url: '/springbootapi/downloadCustomerReport',
            method: "POST",
            body: JSON.stringify(req.body),
            headers: {
                'Content-Type':'application/json'
            },
        }, function (error, res, body) {
            if(error){
                console.log(error);
                response.status(500).send(error);
            }else{
                try {
                    response.send({headers: res.headers, data: res.body})
                }catch(err){
                    response.status(500).send(err)
                }
            }
        }
    )
});
// In the Spring Boot REST API
@RequestMapping(value = "/downloadCustomerReport", method = RequestMethod.POST)
public ResponseEntity<byte[]> downloadCustomerReport(@RequestBody SamplesDataRequestHolderVO samplesDataRequestVO){
byte[] resource = null;
try(Workbook workbook = new XSSFWorkbook();
                ByteArrayOutputStream out = new ByteArrayOutputStream();){
// Include and populate the worksheet
workbook.write(out);
writeToFile(new ByteArrayInputStream(out.toByteArray()));
resource = out.toByteArray();
}


HttpHeaders headers = new HttpHeaders(); 
       headers.setContentType(MediaType.valueOf("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=CR Final.xlsx");

        return ResponseEntity.ok()
                .headers(headers)
                .body(resource);


}

The file saved from Spring Boot and Postman downloads correctly without any issues. However, when attempting to download it through React, it consistently shows corruption. The data received in AJAX is shown as:

'PK�[�N[Content_Types].xml�TIn1'.

Comparing the response data from AJAX and Postman reveals no differences. How can this issue be debugged?

Answer №1

To solve the issue, I successfully implemented encoding the byte array to Base64 within a Springboot controller and returned the encoded string as the response body.

@RequestMapping(value = "/downloadCustomerReport", method = RequestMethod.POST)
    public ResponseEntity<String> downloadCustomerReport(@RequestBody SamplesDataRequestHolderVO samplesDataRequestVO) throws IOException {
        byte[] resource = null;
try(Workbook workbook = new XSSFWorkbook();
                ByteArrayOutputStream out = new ByteArrayOutputStream();){
// Generated worksheet is attached
workbook.write(out);
writeToFile(new ByteArrayInputStream(out.toByteArray()));
resource = out.toByteArray();
}
        HttpHeaders headers = new HttpHeaders(); 
       headers.setContentType(MediaType.valueOf("application/octet-stream"));
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=CR Final.xlsx");
String s = Base64.getEncoder().encodeToString(resource); // Byte array encoding performed here
        return ResponseEntity.ok()
                .headers(headers)
                .body(s);
    }

For the frontend, I utilized the base64StringToBlob function from the blob-util library and converted the type to application/xlsx:

var blob = base64StringToBlob(response.data, 'application/xlsx');

Answer №2

Ensure you include the responseType parameter as "blob" in your Request configuration.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

During the onClick event, the source of this component's variable is unknown

I'm currently working through the React tic-tac-toe tutorial and I have a question regarding the initial i in this function (inside the Game class) that's being passed into handleClick: return ( <div className="game"> <di ...

Addressing the data transfer issue between Spring framework and Next.js using Axios

For my upcoming project, I am considering using a combination of Spring and Next.js. In the past, I have worked on projects using Spring and React. I find the API/route structure in Next.js 13 version to be quite intriguing compared to traditional React ...

Tips on implementing the setTimeout function within a conditional statement?

How can I display an alert message on the screen indicating whether the message was successfully sent (status 200) or if there were errors (else), with the message disappearing after 3 seconds? I typically implement this functionality within the useEffect ...

What could be causing my slider to malfunction?

No errors are being returned by the console. Currently utilizing Unslider. The setup includes: <div class="slider"> <ul> <li><img src="img/one.jpg" alt=""></li> <li><img src="img/one.jpg" ...

What is the jQuery alternative for the classList property in vanilla JavaScript?

Currently, I am working on a collaborative project with two acquaintances. One of the requirements is to stick to either vanilla JavaScript selectors like document.getElementById("thisDiv"); or jQuery selectors such as $("#thisDiv"); to maintain consis ...

Is it possible to apply a click effect to a specific child element of a parent using jQuery?

Struggling to figure out how to modify this jQuery code so that only the parent of the clicked button displays its child. Currently, all children are displayed when any button is clicked, not just the one within the targeted parent. I attempted using $(t ...

Difficulty reloading after updating input using AngularJS ngTable

I'm encountering an issue where I need to utilize ngTable with TableParams to load and modify a table. For instance, when the page initializes, entering a number in the textbox for the first time displays the appropriate number of rows in the table. ...

In NextJS, where is the best place to run sensitive code to ensure it is only executed server-side?

I'm currently exploring the world of NextJS and I am in the process of figuring out how to structure my project with a solid architecture that prioritizes security. However, I find myself at a crossroads when it comes to determining the best place to ...

Tips for incorporating "are you sure you want to delete" into Reactjs

I am currently working with Reactjs and Nextjs. I have a list of blogs and the functionality to delete any blog. However, I would like to display a confirmation message before deleting each item that says "Are you sure you want to delete this item?" How ...

Unlock the power of Formik for extracting values from Material UI Select Fields

Excuse me, I'm trying to grasp and accomplish something with Formik. I have two select fields and I want to pass their selected values to the formik value. Essentially, they retrieve a list of countries and their respective regions from the CountryAr ...

Exploring Event Propagation in AngularJS

Currently, I am working on developing a web application using angularjs for the first time. A key feature that I aim to introduce is the ability for users to create a div in the main window upon clicking on an image in the menu. To achieve this functional ...

Mastering the Art of jQuery: Easily Choosing and Concealing a Div Element

I'm currently facing challenges in removing a div upon successful AJAX completion. The issue I'm encountering is that the word "Added" appears twice after success, indicating that I am not properly selecting the two divs containing it. Any sugges ...

Is there a solution for React Components child component rendering twice?

When I click on the Update Key button, Child1 component renders every time. How can I resolve this issue? Note: I have created three components - one parent component and two child components. When I click on the parent component's button to update th ...

The Ajax request yields a response consisting of an array filled with blank objects

Currently, I am utilizing PHP object-oriented programming to fetch data from the database. The data is retrieved successfully, but when I attempt to make AJAX calls, it returns an array of empty objects. How can I ensure that the objects return the actual ...

Parent-sourced Material Tooltip Text Display

I would like to implement a ToolTip in the following manner: const MyComponent = () => { [open, setOpen] = useState(false); return <div (onClick)={() => {setOpen(!open)}> Click to open tooltip <Tooltip text="some ...

serving files using express.static

I have set up express.static to serve multiple static files: app.use("/assets", express.static(process.cwd() + "/build/assets")); Most of the time, it works as expected. However, in certain cases (especially when downloading many files at once), some fil ...

ZeroClipboard intricate CSS issue

I have a list of images with an option box that appears on mouseover. The box contains an embedded code input field for copying purposes. I recently implemented zeroclipboard to enable the copy function on click. However, when I hover over an image and try ...

Struggling with path detection in react-i18next - any tips?

I have a question about my code. Even though I have specified the language in the path (localhost/fr), it doesn't seem to detect it correctly. Can you help me figure out what's wrong here? import { initReactI18next } from "react-i18next" ...

Struggling to maintain context with axios in React despite diligent use of arrow functions

In my component, I have a function for posting data. Although it works well, the context of my component is lost in the success message. This is puzzling because I am using arrow functions. Why does the "this" context get lost in this situation? The issu ...

Applying the document height to window height ratio to create a scale ranging from 1 to 100

My goal is to create a scroll bar using two divs with heights of 110px and 10px. The smaller one will be nested inside the taller one, allowing for adjustment of its margin-height from 0 to 100px while still fitting within the larger div. When I refer to ...