簡體   English   中英

將 ReactJS 對象下載為文件

[英]Download a ReactJS object as a file

我正在構建一個帶有連接到 Express API 服務器的 ReactJS 前端的應用程序。 對 API 的調用是使用 Ajax 進行的。

在我的一個視圖中,一個表格加載了每一行的“導出”鏈接。 導出鏈接通向調用 API 端點的 React 路由,該 API 端點提供要下載的 CSV 文件。

如果我使用有效請求(在 React 應用程序之外)直接訪問 API 端點,則會在我的瀏覽器中啟動文件下載。 完美的! 但是,遵循 React 頁面中的導出鏈接會嘗試加載調用 API 的視圖。 該表從視圖中消失並被文件內容替換(為了證明我有數據),但沒有下載文件。

我可以強制將響應對象的內容下載為文件嗎? 這會發生在 ajax 成功回調中嗎? 我嘗試使用 javascript,但我在 React 虛擬 DOM 上掙扎......我認為這一定很簡單,但我很難過。

編輯:@Blex 的評論幫助我解決了這個問題! 解決方案已添加到代碼片段中...

這是接收數據的 JSX:

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

根據@blex的注釋添加以下代碼使文件下載工作。 要在上下文中查看它,請查看問題中的成功回調。

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

我在我的React應用程序中使用了一個包jsonexport ,現在我可以在鏈接點擊上下載csv文件了。 這是我做的:

.
.
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

.
.
.

創建一個為CSV提供數據的功能。 它也可以來自網絡請求的回調。 調用此方法時,它將在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);
    });
}

在render函數中使用類似這樣的東西:

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

filedownloadlink有一些要下載的數據時,上面的鏈接將是可見的。

添加以下代碼以供將來參考。 這是為了包括對瀏覽器兼容性的一些額外檢查,以及包含 IE10+ 的額外代碼。

/* Take a blob and force browser to click a link and save it from a download path
     * log out timing
     *
     * @param {Blob}
     * @method saveFile
     */
    function saveFile(blob) {
        const uniqTime = new Date().getTime();
        const filename = `my_file_${uniqTime}`;

        if (navigator.msSaveBlob) { // IE 10+
            console.info('Starting call for ' + 'ie download');
            const csvFormatTimeStart = new Date().getTime();

            const ieFilename = `${filename}.csv`;
            navigator.msSaveBlob(blob, ieFilename);

            const csvFormatTimeEnd = new Date().getTime();
            const csvFormatTime = csvFormatTimeEnd - csvFormatTimeStart;
            console.log('ie download takes ' + csvFormatTime + ' ms to run');
        } else {
            console.info('Starting call for ' + 'regular download');
            const csvFormatTimeStart = new Date().getTime();
            let link = document.createElement("a");
            if (link.download !== undefined) { // feature detection
                // Browsers that support HTML5 download attribute
                var url = URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", filename);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            }

            const csvFormatTimeEnd = new Date().getTime();
            const csvFormatTime = csvFormatTimeEnd - csvFormatTimeStart;
            console.log('regular download takes ' + csvFormatTime + ' ms to run');
        }

        clickEnd = new Date().getTime();
        console.log('The whole process took: ' + (clickEnd - clickStart) + ' ms');
    }

信用應該去這篇文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM