ExpressAPIサーバーに接続するReactJSフロントエンドを使用してアプリケーションを構築しています。 APIの呼び出しは、Ajaxを使用して行われます。
私の見解の1つでは、テーブルが読み込まれ、各行に「エクスポート」リンクがあります。エクスポートリンクは、ダウンロードするCSVファイルを提供するAPIエンドポイントを呼び出すReactルートにつながります。
(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);
});
}
レンダリング関数では、次のようなものを使用します。
{filedownloadlink &&<a download="UserExport.csv" href={filedownloadlink}>Download</a>}
上記のリンクは、filedownloadlink
にダウンロードするデータがある場合に表示されます。