Как скачивать файлы с помощью axios

Я использую axios для основных HTTP-запросов, таких как get и post, и работает хорошо. Теперь мне также нужно иметь возможность загружать файлы excel. Возможно ли это с помощью аксиом. Если это так, у кого-нибудь есть образец кода? Если нет, что еще я могу использовать в приложении для реагирования, чтобы сделать то же самое?

Ответ 1

Когда ответ приходит с загружаемым файлом, заголовки ответа будут выглядеть примерно так:

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

Что вы можете сделать, это создать отдельный компонент, который будет содержать скрытый iframe.

  import * as React from 'react';

  var MyIframe = React.createClass({

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

Теперь вы можете передать URL-адрес загружаемого файла в качестве опоры этому компоненту, поэтому, когда этот компонент получит опору, он выполнит повторную визуализацию и файл будет загружен.

Редактировать: Вы также можете использовать модуль js-file-download. Ссылка на репозиторий Github

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

Axios.get('http://localhost/downloadFile')
   .then((response) => {
        FileDownload(response.data, 'report.csv');
   });

Надеюсь это поможет :)

Ответ 2

Загрузка файлов (с использованием Axios и Security)

Это на самом деле еще сложнее, если вы хотите загружать файлы с помощью 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

Эти шаги в основном выполняются - но значительно осложняются отношением браузера к CORS. Один шаг за раз:

1. Настройте свой (HTTP) сервер

При использовании безопасности на транспорте JavaScript, выполняющийся в браузере, может [по дизайну] получить доступ только к 6 HTTP-заголовкам, фактически отправленным HTTP-сервером. Если мы хотим, чтобы сервер предложил имя файла для загрузки, мы должны сообщить браузеру, что "ОК" для JavaScript должен быть предоставлен доступ к другим заголовкам, где предлагаемое имя файла будет перенесено.

Предположим - ради обсуждения - что мы хотим, чтобы сервер передал предлагаемое имя файла в HTTP-заголовке с именем X-Recommended-Filename. HTTP-сервер сообщает браузеру, что он открыт, чтобы открыть этот полученный пользовательский заголовок для JavaScript/Axios со следующим заголовком:

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, который должен опубликовать отчет Excel:

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

В настоящее время служба испускает бинарный документ (в этом случае отчет Excel), устанавливает правильный тип контента, а также отправляет собственный HTTP-заголовок, содержащий предлагаемое имя файла для использования при сохранении документа.

3. Внедрение обработчика Axios для принятого документа

Здесь есть несколько подводных камней, поэтому пусть все детали правильно настроены:

  • Служба отвечает на @GET (т.е. HTTP GET), поэтому вызов axios должен быть "axios.get(...)".
  • Документ передается как поток байтов, поэтому вы должны указывать axios для обработки ответа как HTML5 Blob. (I.e. responseType: 'blob').
  • В этом случае библиотека JavaScript с файловыми заставками используется для открытия диалогового окна браузера. Однако вы могли бы выбрать другое.

Реализация скелета Axios будет тогда чем-то вроде:

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

Ответ 3

Более общее решение

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

Полные кредиты: https://gist.github.com/javilobo8

Ответ 4

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

Ответ 5

Это очень простой код JavaScript для запуска загрузки для пользователя:

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

Вы не хотите/не нуждаетесь в axios для этой операции; стандартно просто позволить браузеру делать это.

Примечание. Если для загрузки требуется авторизация, это может не сработать. Я уверен, что вы можете использовать куки файлы для авторизации такого запроса, если он выполняется в пределах одного домена, но в любом случае это может не сработать сразу.


Что касается того, возможно ли это... не со встроенным механизмом загрузки файлов, нет.

Ответ 6

Решение Axios.post с IE и другими браузерами

Нашел здесь несколько невероятных решений. Но они часто не учитывают проблемы с браузером 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();
                    }
                }
            );

Пример выше для файлов Excel, но с небольшими изменениями можно применять любой формат.

И на сервере я сделал это, чтобы отправить Excel

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

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

Ответ 7

Функция для вызова API с помощью axios:

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

Вызовите функцию, а затем загрузите полученный файл Excel:

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

Хитрость заключается в создании невидимого тега привязки в render() и добавлении Refact ref позволяющего запускать клик, когда у нас есть ответ axios:

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

Ответ 9

Мой ответ - общий хак. Я только что создал ссылку, которая выглядит как кнопка и добавляет к ней 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-дизайна.