कैसे axios का उपयोग कर फ़ाइलों को डाउनलोड करने के लिए


124

मैं GET और POST जैसे बुनियादी http अनुरोधों के लिए axios का उपयोग कर रहा हूं, और यह अच्छी तरह से काम करता है। अब मुझे एक्सेल फाइल भी डाउनलोड करने में सक्षम होना चाहिए। क्या यह axios के साथ संभव है? यदि ऐसा है तो किसी के पास कुछ नमूना कोड है? यदि नहीं, तो मैं ऐसा करने के लिए एक रिएक्ट एप्लिकेशन में और क्या उपयोग कर सकता हूं?


हम इस समाधान का उपयोग एक्सेल फाइल को डाउनलोड करने के लिए कर सकते हैं। stackoverflow.com/questions/57127361/…
Md। नाज़रुल इस्लाम

जवाबों:


107

जब प्रतिक्रिया एक डाउनलोड करने योग्य फ़ाइल के साथ आती है, तो प्रतिक्रिया हेडर कुछ इस तरह होगा

Content-Disposition: "attachment;filename=report.xls"
Content-Type: "application/octet-stream" // or Content-type: "application/vnd.ms-excel"

आप जो कर सकते हैं वह एक अलग घटक बना सकता है, जिसमें एक छिपा हुआ आइफ्रेम होगा।

  import * as React from 'react';

  var MyIframe = React.createClass({

     render: function() {
         return (
           <div style={{display: 'none'}}>
               <iframe src={this.props.iframeSrc} />
           </div>
         );
     }
  });

अब, आप इस घटक को प्रोप के रूप में डाउनलोड करने योग्य फ़ाइल के यूआरएल को पास कर सकते हैं, इसलिए जब यह घटक प्रोप प्राप्त करेगा, तो यह फिर से प्रस्तुत करेगा और फ़ाइल डाउनलोड हो जाएगी।

संपादित करें: आप जेएस-फाइल-डाउनलोड मॉड्यूल का भी उपयोग कर सकते हैं । जीथुब रेपो से लिंक करें

const FileDownload = require('js-file-download');

Axios({
  url: 'http://localhost/downloadFile',
  method: 'GET',
  responseType: 'blob', // Important
}).then((response) => {
    FileDownload(response.data, 'report.csv');
});

उम्मीद है की यह मदद करेगा :)


1
धन्यवाद। क्या आप मुझे बता सकते हैं कि क्या यह अजाक्स शैली में है। अच्छा होगा कि पेज को ब्लॉक न करें।
डेविड चोई

हां, पेज ब्लॉक नहीं किया जाएगा। जब आप उस घटक को प्रोप के रूप में यूआरएल पास करते हैं, तो फ़ाइल स्वचालित रूप से डाउनलोड हो जाएगी। आपको कुछ भी करने की आवश्यकता नहीं होगी।
हार्दिक मोधा

एक और प्रश्न। मेरे मामले में डाउनलोड की जा रही फ़ाइल गतिशील रूप से कुछ मापदंडों के साथ बनाई गई है। तो यह वास्तव में एक सुसंगत स्थान नहीं है। इस प्रकार के परिदृश्य के लिए मैं किस url को भेजूं? उदाहरण के लिए अगर मैंने axios.post ('एपी / गेटमाइन्फ़ेलिफ़ाइल', परम) कहा;
डेविड चोई

जैसा कि इस उत्तर में बताया गया है । अक्षीय अनुक्रिया ऑब्जेक्ट में, अनुरोध के अंदर अस नामक क्षेत्र होता है responseURL, शायद यह वह URL है जो आप चाहते हैं।
हार्दिक मोधा

1
मैंने इसका अनुसरण किया और फ़ाइल डाउनलोड करने में सक्षम था। लेकिन फ़ाइल टूट गई है (काम नहीं करता है)। हालाँकि, अगर मैं रीडायरेक्शन (window.location.href) फ़ाइल डाउनलोड का उपयोग करता हूं और पूरी तरह से काम करता हूं। क्या कोई मेरी मदद कर सकता है, कृपया। ( stackoverflow.com/questions/56306008/… )
थिडासा पंकजा

125

एक अधिक सामान्य समाधान

axios({
  url: 'http://api.dev/file-download', //your url
  method: 'GET',
  responseType: 'blob', // important
}).then((response) => {
   const url = window.URL.createObjectURL(new Blob([response.data]));
   const link = document.createElement('a');
   link.href = url;
   link.setAttribute('download', 'file.pdf'); //or any other extension
   document.body.appendChild(link);
   link.click();
});

Https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743 पर quirks देखें

इसका पूरा श्रेय: https://gist.github.com/javilobo8 को जाता है


12
समाधान के लिए धन्यवाद। दूसरों के लिए बस कुछ नोट्स: जबकि यह बहुत सारे उपयोग के मामलों के लिए काम कर सकता है, लेकिन बड़े फ़ाइल आकारों के लिए आप डाउनलोड प्रगति नहीं देख पाएंगे। और यह ब्राउज़र में अतिरिक्त मेमोरी लेगा। जैसा कि अन्य समाधानों में दिया गया है, लेकिन वर्तनी नहीं है, हेडर 'सामग्री-विवाद: अनुलग्नक' का उपयोग करने के लिए सामान्य दृष्टिकोण है; इसलिए ब्राउज़र इसे एक देशी डाउनलोड (पूर्वोक्त डाउनलोड प्रगति + डिस्क पर प्रत्यक्ष डाउनलोड) के रूप में मानेगा।
जॉन ली

सर्वर साइड पर भी जब मैं Content-Desposition हेडर सेट करता हूं, तो यह डाउनलोड प्रगति की अनुमति नहीं देता है।
ह्यूगी

4
इसके लिए धन्यवाद। सोच रहा था कि फ़ाइल सामग्री सही ढंग से क्यों दिखाई नहीं दे रही थी। मुझे पता चला कि मैं गायब थाresponseType: 'blob'
AliAvci

यह फ़ाइल को मेमोरी के लिए पहली प्रतिक्रिया के रूप में डाउनलोड नहीं करता है (ब्राउज़र के बिना वास्तव में डाउनलोड प्रगति दिखा रहा है) जब फ़ाइल को मेमोरी में एक बूँद के रूप में डाउनलोड किया जाता है, तो केवल ब्राउज़र इसे डाउनलोड फ़ाइल में सहेजने का प्रयास करेगा ..
रिकी -U

@ रिकी-यू हां आप सही कह रहे हैं कि xhr रिक्वेस्ट भेजी जाएगी और जब रिस्पांस आएगा तो यह मेमोरी में बफ़र हो जाएगा और बाद में responseपूरा होने पर वेरिएबल में स्टोर हो जाएगा । फिर createObjectURLइस डेटा के लिए एक स्थानीय यूआरएल बनाता है जिसे एक <a> नेविगेट कर सकता है।
विनी

50

फ़ाइलें डाउनलोड करना (Axios और सुरक्षा का उपयोग करके)

यह वास्तव में और भी जटिल है जब आप Axios और सुरक्षा के कुछ साधनों का उपयोग करके फ़ाइलों को डाउनलोड करना चाहते हैं। किसी अन्य व्यक्ति को यह पता लगाने में बहुत अधिक समय खर्च करने से रोकने के लिए, मुझे इसके माध्यम से चलना चाहिए।

आपको 3 चीजें करने की आवश्यकता है:

1. Configure your server to permit the browser to see required HTTP headers
2. Implement the server-side service, and making it advertise the correct file type for the downloaded file.
3. Implementing an Axios handler to trigger a FileDownload dialog within the browser

ये चरण ज्यादातर उल्लेखनीय हैं - लेकिन कॉर्स के ब्राउज़र के संबंध से काफी जटिल हैं। एक समय में एक ही कदम:

1. अपने (HTTP) सर्वर को कॉन्फ़िगर करें

परिवहन सुरक्षा को नियोजित करते समय, जावास्क्रिप्ट एक ब्राउज़र के भीतर निष्पादित कर सकता है [डिज़ाइन द्वारा] HTTP हेडर के केवल 6 का उपयोग वास्तव में HTTP सर्वर द्वारा भेजा गया है। यदि हम सर्वर को डाउनलोड के लिए फ़ाइल नाम सुझाना चाहते हैं, तो हमें ब्राउज़र को सूचित करना होगा कि जावास्क्रिप्ट के लिए "ओके" अन्य हेडर तक पहुँच दी जाए, जहाँ सुझाया गया फ़ाइल नाम पहुँचाया जाएगा।

आइए हम चर्चा करें - चर्चा के लिए - कि हम चाहते हैं कि सर्वर सुझाए गए फ़ाइलनाम को एक HTTP हेडर के भीतर एक्स-सुझाव-फाइलन नाम से प्रसारित करे । HTTP सर्वर ब्राउज़र को बताता है कि इस प्राप्त कस्टम हेडर को जावास्क्रिप्ट / एक्सियोस के साथ निम्नलिखित हेडर के साथ उजागर करना ठीक है:

Access-Control-Expose-Headers: X-Suggested-Filename

इस शीर्ष लेख को सेट करने के लिए अपने HTTP सर्वर को कॉन्फ़िगर करने का सटीक तरीका उत्पाद से उत्पाद में भिन्न होता है।

इन मानक शीर्ष लेखों की पूरी व्याख्या और विस्तृत विवरण के लिए https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers देखें ।

2. सर्वर-साइड सेवा को लागू करें

आपके सर्वर-साइड सेवा कार्यान्वयन को अब 2 चीजें करनी चाहिए:

1. Create the (binary) document and assign correct ContentType to the response
2. Assign the custom header (X-Suggested-Filename) containing the suggested file name for the client

यह आपके चुने हुए प्रौद्योगिकी स्टैक के आधार पर विभिन्न तरीकों से किया जाता है। मैं JavaEE 7 मानक का उपयोग करके एक उदाहरण को स्केच करूँगा जो एक एक्सेल रिपोर्ट का उत्सर्जन करना चाहिए:

@GET
@Path("/report/excel")
@Produces("application/vnd.ms-excel")
public Response getAllergyAndPreferencesReport() {

    // Create the document which should be downloaded
    final byte[] theDocumentData = .... 

    // Define a suggested filename
    final String filename = ... 

    // Create the JAXRS response
    // Don't forget to include the filename in 2 HTTP headers: 
    //
    // a) The standard 'Content-Disposition' one, and
    // b) The custom 'X-Suggested-Filename'  
    //
    final Response.ResponseBuilder builder = Response.ok(
            theDocumentData, "application/vnd.ms-excel")
            .header("X-Suggested-Filename", fileName);
    builder.header("Content-Disposition", "attachment; filename=" + fileName);

    // All Done.
    return builder.build();
}

सेवा अब द्विआधारी दस्तावेज़ (एक एक्सेल रिपोर्ट, इस मामले में) का उत्सर्जन करती है, सही सामग्री प्रकार सेट करती है - और दस्तावेज़ को सहेजते समय उपयोग करने के लिए सुझाए गए फ़ाइलनाम वाले कस्टम HTTP हेडर भी भेजता है।

3. प्राप्त दस्तावेज के लिए एक Axios हैंडलर लागू करें

यहाँ कुछ नुकसान हैं, तो चलिए सुनिश्चित करते हैं कि सभी विवरण सही ढंग से कॉन्फ़िगर किए गए हैं:

  1. सेवा @GET (HTTP HTTP GET) पर प्रतिक्रिया देती है, इसलिए अक्षीय कॉल 'axios.get (...)' होनी चाहिए।
  2. दस्तावेज़ को बाइट्स की एक धारा के रूप में प्रेषित किया जाता है, इसलिए आपको प्रतिक्रिया को एचटीएमएल 5 ब्लॉब के रूप में व्यवहार करने के लिए axios को बताना होगा। (यानी प्रतिक्रियाप्रकार: 'बूँद' )।
  3. इस स्थिति में, फ़ाइल-सेवर जावास्क्रिप्ट लाइब्रेरी का उपयोग ब्राउज़र संवाद को खोलने के लिए किया जाता है। हालाँकि, आप दूसरा चुन सकते हैं।

कंकाल कुल्हाड़ी कार्यान्वयन तब की तर्ज पर कुछ होगा:

 // Fetch the dynamically generated excel document from the server.
 axios.get(resource, {responseType: 'blob'}).then((response) => {

    // Log somewhat to show that the browser actually exposes the custom HTTP header
    const fileNameHeader = "x-suggested-filename";
    const suggestedFileName = response.headers[fileNameHeader];'
    const effectiveFileName = (suggestedFileName === undefined
                ? "allergierOchPreferenser.xls"
                : suggestedFileName);
    console.log("Received header [" + fileNameHeader + "]: " + suggestedFileName
                + ", effective fileName: " + effectiveFileName);

    // Let the user save the file.
    FileSaver.saveAs(response.data, effectiveFileName);

    }).catch((response) => {
        console.error("Could not Download the Excel report from the backend.", response);
    });

21
"फाइलसेवर" क्या है?
मेन पाल

6
यह डाउनलोड फ़ाइलों को संभालने के लिए एक पुस्तकालय है, github.com/eligrey/FileSaver.js/#filesaverjs
Radi

3
यह काम करता है, लेकिन इसके content-dispositionबजाय हेडर का उपयोग करने की सिफारिश की जाती है x-suggested-filename
रोजडी कासिम

14

IE और अन्य ब्राउज़रों के साथ Axios.post समाधान

मुझे यहां कुछ अविश्वसनीय समाधान मिले हैं। लेकिन वे अक्सर IE ब्राउज़र के साथ समस्याओं को ध्यान में नहीं रखते हैं। शायद यह किसी और को कुछ समय बचाएगा।

 axios.post("/yourUrl"
                , data,
                {responseType: 'blob'}
            ).then(function (response) {
                    let fileName = response.headers["content-disposition"].split("filename=")[1];
                    if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE variant
                        window.navigator.msSaveOrOpenBlob(new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}),
                            fileName);
                    } else {
                        const url = window.URL.createObjectURL(new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}));
                        const link = document.createElement('a');
                        link.href = url;
                        link.setAttribute('download', response.headers["content-disposition"].split("filename=")[1]);
                        document.body.appendChild(link);
                        link.click();
                    }
                }
            );

उदाहरण ऊपर एक्सेल फ़ाइलों के लिए है, लेकिन थोड़े बदलाव के साथ इसे किसी भी प्रारूप में लागू किया जा सकता है।

और सर्वर पर मैंने एक्सेल फाइल भेजने के लिए ऐसा किया है।

response.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exceptions.xlsx")

9

Axios के साथ API कॉल करने का कार्य:

  function getFileToDownload (apiUrl) {
     return axios.get(apiUrl, {
       responseType: 'arraybuffer',
       headers: {
         'Content-Type': 'application/json'
       }
     })
  }

फ़ंक्शन को कॉल करें और फिर आपके द्वारा प्राप्त एक्सेल फ़ाइल डाउनलोड करें:

getFileToDownload('putApiUrlHere')
  .then (response => {
      const type = response.headers['content-type']
      const blob = new Blob([response.data], { type: type, encoding: 'UTF-8' })
      const link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'file.xlsx'
      link.click()
  })

8
        axios.get(
            '/app/export'
        ).then(response => {    
            const url = window.URL.createObjectURL(new Blob([response]));
            const link = document.createElement('a');
            link.href = url;
            const fileName = `${+ new Date()}.csv`// whatever your file name .
            link.setAttribute('download', fileName);
            document.body.appendChild(link);
            link.click();
            link.remove();// you need to remove that elelment which is created before.
})

7

उपयोगकर्ता के लिए डाउनलोड को ट्रिगर करने के लिए यह बहुत सरल जावास्क्रिप्ट कोड है:

window.open("<insert URL here>")

आप इस ऑपरेशन के लिए axios नहीं चाहते / चाहते हैं; यह मानक होना चाहिए कि ब्राउजर को यह काम करने दे।

नोट: यदि आपको डाउनलोड के लिए प्राधिकरण की आवश्यकता है तो यह काम नहीं कर सकता है। मुझे पूरा यकीन है कि आप इस तरह के अनुरोध को अधिकृत करने के लिए कुकीज़ का उपयोग कर सकते हैं, बशर्ते वह एक ही डोमेन के भीतर हो, लेकिन इसकी परवाह किए बिना, यह ऐसे मामले में तुरंत काम नहीं कर सकता है।


जैसे कि यह संभव है ... इन-बिल्ट फ़ाइल डाउनलोडिंग तंत्र के साथ नहीं, नहीं


12
प्राधिकरण हेडर?
एजाज करीम

यदि आपको टोकन भेजने की आवश्यकता है तो क्या होगा?
user3808307

यदि आप सर्वर को नियंत्रित करते हैं, तो आप बस एक्सेस टोकन को कुकी के रूप में संग्रहीत कर सकते हैं, और ब्राउज़र इसे आपके सर्वर के किसी भी अनुरोध में जोड़ देगा। medium.com/@ryanchenkie_40935/…
मल्टीहैंटर

1
@CharithJayasanka हां, मेरा ऐसा मानना ​​है।
मल्टीहंटर

2

चाल एक अदृश्य लंगर टैग बनाने के लिए है render()और एक प्रतिक्रिया जोड़ने के refलिए एक क्लिक को ट्रिगर करने की अनुमति देता है जब हमारे पास अक्षीय प्रतिक्रिया होती है:

class Example extends Component {
    state = {
        ref: React.createRef()
    }

    exportCSV = () => {
        axios.get(
            '/app/export'
        ).then(response => {
            let blob = new Blob([response.data], {type: 'application/octet-stream'})
            let ref = this.state.ref
            ref.current.href = URL.createObjectURL(blob)
            ref.current.download = 'data.csv'
            ref.current.click()
        })
    }

    render(){
        return(
            <div>
                <a style={{display: 'none'}} href='empty' ref={this.state.ref}>ref</a>
                <button onClick={this.exportCSV}>Export CSV</button>
            </div>
        )
    }
}

यहाँ प्रलेखन है: https://reactjs.org/docs/refs-and-the-dom.html । आप यहां एक समान विचार पा सकते हैं: https://thewebtier.com/snippets/download-files-with-axios/


0

यह मेरे लिए काम किया। मैंने इस समाधान को reactJS में लागू किया

const requestOptions = {`enter code here`
method: 'GET',
headers: { 'Content-Type': 'application/json' }
};

fetch(`${url}`, requestOptions)
.then((res) => {
    return res.blob();
})
.then((blob) => {
    const href = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = href;
    link.setAttribute('download', 'config.json'); //or any other extension
    document.body.appendChild(link);
    link.click();
})
.catch((err) => {
    return Promise.reject({ Error: 'Something Went Wrong', err });
})

-1

अक्षीय POST अनुरोध के लिए, अनुरोध कुछ इस तरह से होना चाहिए: यहां कुंजी यह है कि पोस्ट के तृतीय पैरामीटर में फ़ील्ड्स responseTypeऔर headerफ़ील्ड होना चाहिए। दूसरा पैरामीटर अनुप्रयोग पैरामीटर है।

export const requestDownloadReport = (requestParams) => async dispatch => { 
  let response = null;
  try {
    response = await frontEndApi.post('createPdf', {
      requestParams: requestParams,
    },
    {
      responseType: 'arraybuffer', // important...because we need to convert it to a blob. If we don't specify this, response.data will be the raw data. It cannot be converted to blob directly.
      headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/pdf'
      }
  });          
  }
  catch(err) {
    console.log('[requestDownloadReport][ERROR]', err);
    return err
  }

  return response;
}

-4

मेरा जवाब कुल हैक है - मैंने सिर्फ एक लिंक बनाया है जो एक बटन की तरह दिखता है और उस पर URL जोड़ें।

<a class="el-button"
  style="color: white; background-color: #58B7FF;"
  :href="<YOUR URL ENDPOINT HERE>"
  :download="<FILE NAME NERE>">
<i class="fa fa-file-excel-o"></i>&nbsp;Excel
</a>

मैं उत्कृष्ट VueJs का उपयोग कर रहा हूं इसलिए विषम एनोटेशन, हालांकि, यह समाधान फ्रेमवर्क एग्नोस्टिक है। विचार किसी भी HTML आधारित डिजाइन के लिए काम करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.