Я использую axios для основных HTTP-запросов, таких как get и post, и работает хорошо. Теперь мне также нужно иметь возможность загружать файлы excel. Возможно ли это с помощью аксиом. Если это так, у кого-нибудь есть образец кода? Если нет, что еще я могу использовать в приложении для реагирования, чтобы сделать то же самое?
Как скачивать файлы с помощью axios
Ответ 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> Excel
</a>
Я использую отличный VueJs, поэтому нечетные анотации, однако, это решение является агностиком рамки. Идея будет работать для любого HTML-дизайна.