Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download a ReactJS object as a file

I am building an application with a ReactJS front end that connects to an Express API server. Calls to the API are made using Ajax.

In one of my views, a table loads with "Export" links on each row. The Export links lead to a React route that calls an API endpoint which provides a CSV file to download.

If I hit the API endpoint directly with a valid request (outside the React app), a file download is initiated in my browser. Perfect! However, following the Export link from the React page attempts to load the view where the call to the API occurs. The table disappears from the view and is replaced by the file contents (on purpose to prove I have the data) but no file is downloaded.

Can I force a download of the contents of the response object as a file? Could this take place in the ajax success callback? I made an attempt with javascript but I'm struggling with the React virtual DOM... I assume this must be pretty straight forward but I'm stumped.

EDIT: Comments by @Blex helped me solve this issue! The solution is added to the code snippet...

Here is the JSX that receives 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>
            )
    }
});
like image 377
fryeguy Avatar asked Jul 03 '15 22:07

fryeguy


People also ask

How do I download a file from react JS?

Use the download Attribute to Download Files in React Typically, web developers use the anchor element <a> to navigate another page. The <a> element also accepts the download attribute. It tells the browser to save the file located at the specified URL instead of changing the URL.

How do you download fetch response in React as file?

One possible solution could be to send an Ajax request prior to the download (in Widget. js) to confirm the server responds to a GET request to the download file path. Then, if successful, trigger the download.

How do I download a PDF in React?

It is possible by using the fetch() method provided by Java Script. The PDF file will be placed in the public folder of React JS application folder structure. Approach: To accomplish this task we do not need to create any new component, we will use one single component named “App.


2 Answers

Adding the following code based on comments by @blex got the file download working. To see it 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();
like image 134
fryeguy Avatar answered Sep 25 '22 15:09

fryeguy


I used a package jsonexport in my React app and now I am able to download the csv file on a link click. Here is 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 CSV. It can also be in a callback from a network request. When this method is called, it will set value in filedownloadlink state.

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 filedownloadlink has some data to download.

like image 42
Neo Avatar answered Sep 25 '22 15:09

Neo