Load ReactJS object as file

I am creating an app with ReactJS frontend that connects to Express API server. API calls are made using Ajax.

In one of my views, the table is loaded with Export links on each row. The export links lead to a React route that calls an API endpoint that provides a downloadable CSV file.

If I hit the API endpoint directly with a valid request (outside of the React app) the file download starts in my browser. Fine! However, by following the Export link on the React page, you are trying to load the view in which the API call is made. The table disappears from the view and is replaced by the contents of the file (to prove I have data), but the file is not loaded.

Can I force the content of the response object to be downloaded as a file? Can this happen in the ajax callback? I made a try with javascript, but I am struggling with React virtual DOM ... I guess it should be pretty simple, but I'm stumped.

EDIT: @Blex's comments helped me solve this problem! Solution added in code snippet ...

Here is the JSX that gets the data:

module.exports = React.createClass({

    mixins: [Router.State],
    getInitialState: function() {
        return {
            auth: getAuthState(),
            export: [],
            passedParams: this.getParams()
        };
    },

    componentDidMount: function(){
        $.ajax({
            type: 'GET',
            url: ''+ API_URL +'/path/to/endpoint'+ this.state.passedParams.id +'/export',
            dataType: 'text',
            headers: {
                'Authorization': 'Basic ' + this.state.auth.base + ''
            },
            success: function (res) {
                // can I force a download of res here?
                console.log('Export Result Success -- ', res);
                if(this.isMounted()){
                    console.log('Export Download Data -- ', res);
                    this.setState({export: res[1]});
                    // adding the next three lines solved my problem
                    var data = new Blob([res], {type: 'text/csv'});
                    var csvURL = window.URL.createObjectURL(data);
                    //window.open(csvURL);
                    // then commenting out the window.open & replacing
                    // with this allowed a file name to be passed out
                    tempLink = document.createElement('a');
                    tempLink.href = csvURL;
                    tempLink.setAttribute('download', 'filename.csv');
                    tempLink.click();
                }
            }.bind(this),
            error: function (data) {
                console.log('Export Download Result Error -- ', data);
            }
        });
    },

    render: function(){
        console.log('exam assignment obj -- ', this.state.passedParams.name);
        var theFileContents = this.state.export;
            return(
            <div className="row test-table">
                <table className="table" >
                    <tr className="test-table-headers">
                    {theFileContents} // this loads the contents
                    // can I auto download theFileContents?
                    </tr>
                </table>
            </div>
            )
    }
});

      

+6


source to share


2 answers


Adding the following code based on @blex comments triggered the file upload. To see this in context, take a look at the success callback in the question.



var data = new Blob([res], {type: 'text/csv'});
var csvURL = window.URL.createObjectURL(data);
tempLink = document.createElement('a');
tempLink.href = csvURL;
tempLink.setAttribute('download', 'filename.csv');
tempLink.click();

      

+14


source


I used the jsonexport package in my React app and now I can download the CSV file from the link. Here's what I did:

.
.
import React, {useState,useEffect} from 'react';// I am using React Hooks
import * as jsonexport from "jsonexport/dist";
.
.
.
const [filedownloadlink, setFiledownloadlink] = useState("");//To store the file download link

.
.
.


      

Create a function that will provide data for the CSV. It can also be a callback from a network request. When this method is called, it sets the value to state filedownloadlink

.

function handleSomeEvent(){
var contacts = [{
        name: 'Bob',
        lastname: 'Smith'
    },{
        name: 'James',
        lastname: 'David'
    },{
        name: 'Robert',
        lastname: 'Miller' 
    },{
        name: 'David',
        lastname: 'Martin'
    }];

    jsonexport(contacts,function(err, csv){
        if(err) return console.log(err);
        var myURL = window.URL || window.webkitURL //window.webkitURL works in Chrome and window.URL works in Firefox
        var csv = csv;  
        var blob = new Blob([csv], { type: 'text/csv' });  
        var csvUrl = myURL.createObjectURL(blob);
        setFiledownloadlink(csvUrl);
    });
}

      



In the render function, use something like this:

{filedownloadlink &&<a download="UserExport.csv" href={filedownloadlink}>Download</a>}

      

The above link will be visible when you filedownloadlink

have data to download.

0


source







All Articles