ब्राउज़र तकनीक वर्तमान में सीधे अजाक्स अनुरोध से फ़ाइल डाउनलोड करने का समर्थन नहीं करती है। चारों ओर का काम एक छिपी हुई फॉर्म को जोड़ने और ब्राउज़र को सहेजें संवाद को ट्रिगर करने के लिए दृश्यों के पीछे सबमिट करना है।
मैं एक मानक फ्लक्स कार्यान्वयन चल रहा हूँ तो मुझे यकीन है कि क्या सही Redux (प्रसारण) कोड होना चाहिए नहीं कर रहा हूँ, लेकिन कार्यप्रवाह मैं सिर्फ एक फ़ाइल डाउनलोड के लिए बनाए गए इस प्रकार है ...
- मेरे पास
FileDownload
नामक एक प्रतिक्रिया घटक है। यह सब घटक एक छिपी हुई प्रपत्र प्रस्तुत करता है और फिर, componentDidMount
के अंदर, तुरंत फॉर्म सबमिट करें और इसे onDownloadComplete
प्रोप पर कॉल करें।
- मेरे पास एक और प्रतिक्रिया घटक है, हम इसे डाउनलोड बटन/आइकन (वास्तव में ... तालिका में प्रत्येक आइटम के लिए एक) के साथ
Widget
पर कॉल करेंगे। Widget
में संबंधित कार्रवाई और स्टोर फ़ाइलें हैं। Widget
आयात FileDownload
।
Widget
डाउनलोड से संबंधित दो विधियां हैं: handleDownload
और handleDownloadComplete
।
Widget
स्टोर में downloadPath
नामक एक संपत्ति है। यह डिफ़ॉल्ट रूप से null
पर सेट है। जब यह मान null
पर सेट किया गया है, तो कोई फ़ाइल डाउनलोड प्रगति पर नहीं है और Widget
घटक FileDownload
घटक प्रस्तुत नहीं करता है।
Widget
में बटन/आइकन पर क्लिक करने से handleDownload
विधि कॉल होती है जो downloadFile
क्रिया को ट्रिगर करती है। downloadFile
कार्रवाई एक अजाक्स अनुरोध नहीं करता है। यह DOWNLOAD_FILE
ईवेंट को फ़ाइल डाउनलोड करने के लिए downloadPath
के साथ भेजकर स्टोर में भेजता है। स्टोर downloadPath
बचाता है और एक परिवर्तन घटना उत्सर्जित करता है।
- के बाद से वहाँ अब एक
downloadPath
है, Widget
downloadPath
के साथ-साथ onDownloadComplete
के लिए मूल्य के रूप में handleDownloadComplete
विधि सहित आवश्यक रंगमंच की सामग्री में गुजर FileDownload
प्रस्तुत करना होगा।
- जब
FileDownload
प्रस्तुत किया जाता है और फॉर्म method="GET"
(POST भी काम करना चाहिए) और action={downloadPath}
के साथ सबमिट किया गया है, तो सर्वर प्रतिक्रिया अब लक्ष्य डाउनलोड फ़ाइल के लिए ब्राउज़र के सहेजें संवाद को ट्रिगर करेगी (आईई 9/10, नवीनतम फ़ायरफ़ॉक्स और क्रोम में परीक्षण किया गया है))।
- फॉर्म सबमिट करने के तुरंत बाद,
onDownloadComplete
/handleDownloadComplete
कहा जाता है। यह एक और क्रिया को ट्रिगर करता है जो DOWNLOAD_FILE
ईवेंट भेजता है। हालांकि, इस बार downloadPath
null
पर सेट है। स्टोर downloadPath
को null
के रूप में सहेजता है और एक परिवर्तन ईवेंट उत्सर्जित करता है।
- चूंकि अब
downloadPath
FileDownload
घटक Widget
में प्रस्तुत नहीं किया गया है और दुनिया एक सुखद जगह है।
Widget.js - आंशिक कोड केवल
import FileDownload from './FileDownload';
export default class Widget extends Component {
constructor(props) {
super(props);
this.state = widgetStore.getState().toJS();
}
handleDownload(data) {
widgetActions.downloadFile(data);
}
handleDownloadComplete() {
widgetActions.downloadFile();
}
render() {
const downloadPath = this.state.downloadPath;
return (
// button/icon with click bound to this.handleDownload goes here
{downloadPath &&
<FileDownload
actionPath={downloadPath}
onDownloadComplete={this.handleDownloadComplete}
/>
}
);
}
widgetActions.js - आंशिक कोड केवल
export function downloadFile(data) {
let downloadPath = null;
if (data) {
downloadPath = `${apiResource}/${data.fileName}`;
}
appDispatcher.dispatch({
actionType: actionTypes.DOWNLOAD_FILE,
downloadPath
});
}
widgetStore.js - आंशिक कोड केवल
let store = Map({
downloadPath: null,
isLoading: false,
// other store properties
});
class WidgetStore extends Store {
constructor() {
super();
this.dispatchToken = appDispatcher.register(action => {
switch (action.actionType) {
case actionTypes.DOWNLOAD_FILE:
store = store.merge({
downloadPath: action.downloadPath,
isLoading: !!action.downloadPath
});
this.emitChange();
break;
FileDownload। जेएस
- कॉम प्रतिलिपि, पूरी तरह से कार्यात्मक कोड कॉपी और पेस्ट के लिए तैयार
- बैबेल 6.x ["es2015", "प्रतिक्रिया", "चरण -0"]
- फॉर्म display: none
होने की आवश्यकता है जो " छिपा "className
है के लिए
import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
function getFormInputs() {
const {queryParams} = this.props;
if (queryParams === undefined) {
return null;
}
return Object.keys(queryParams).map((name, index) => {
return (
<input
key={index}
name={name}
type="hidden"
value={queryParams[name]}
/>
);
});
}
export default class FileDownload extends Component {
static propTypes = {
actionPath: PropTypes.string.isRequired,
method: PropTypes.string,
onDownloadComplete: PropTypes.func.isRequired,
queryParams: PropTypes.object
};
static defaultProps = {
method: 'GET'
};
componentDidMount() {
ReactDOM.findDOMNode(this).submit();
this.props.onDownloadComplete();
}
render() {
const {actionPath, method} = this.props;
return (
<form
action={actionPath}
className="hidden"
method={method}
>
{getFormInputs.call(this)}
</form>
);
}
}
@nate सीए एन हेडर जानकारी इस फॉर्म सबमिशन के साथ पैक किया जा सकता है? – charlie
@charlie यह एक मानक HTML फॉर्म सबमिट है। आप सामग्री-प्रकार HTTP शीर्षलेख के तीन अलग-अलग मान निर्दिष्ट करने के लिए 'enctype' विशेषता का उपयोग कर सकते हैं, लेकिन यह सब कुछ है। [प्रेषण फ़ॉर्म डेटा] (https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Sending_and_retrieving_form_data) MDN पर पृष्ठ उपयोगी हो सकता है। शीर्षक वाले अनुभाग पर एक नज़र डालें * एक विशेष मामला: फाइलें भेजना *। हमारे पास एक उपयोग केस है जहां हम पहले डाउनलोड फ़ाइल उत्पन्न करने के लिए एक अजाक्स अनुरोध भेजते हैं, फिर हम डाउनलोड करते हैं। यदि आप उस विकल्प का उपयोग कर सकते हैं, तो आपके अजाक्स अनुरोध में हेडर पर अधिक नियंत्रण होगा। – Nate
यह उदाहरण बहुत उपयोगी है, लेकिन यह अभी भी मुझे स्पष्ट नहीं है कि यह कार्यान्वयन इस बारे में जानता है कि फ़ाइल डाउनलोड की गई है या नहीं। मैं देखता हूं कि सबमिट करने के बाद "ऑनडाउनलोड" को सिंक्रनाइज़ कहा जाता है, क्या आप केवल यह धारणा बना रहे हैं कि कोई त्रुटि नहीं है और सर्वर को अनुरोध प्राप्त होता है? – Himmel