Загрузите содержимое текста /csv в виде файлов с сервера в Angular
Я пытаюсь передать файл csv
с сервера node.js. Часть сервера очень проста:
server.get('/orders' function(req, res) {
res.setHeader('content-type', 'text/csv');
res.setHeader('content-disposition', 'attachment; filename='orders.csv');
return orders.pipe(res); // assuming orders is a csv file readable stream (doesn't have to be a stream, can be a normal response)
}
В моем контроллере angular я пытаюсь сделать что-то вроде этого
$scope.csv = function() {
$http({method: 'GET', url: '/orders'});
};
Эта функция вызывается, когда нажимаете кнопку с ng-click
на мой взгляд:
<button ng-click="csv()">.csv</button>
Я просмотрел другие ответы о загрузке файлов с сервера в Angular, но не нашел ничего, что сработало для меня. Есть ли общий способ сделать это? Кажется, что-то должно быть простым.
Ответы
Ответ 1
Служба $http
возвращает a promise
, которая имеет два метода обратного вызова, как показано ниже.
$http({method: 'GET', url: '/someUrl'}).
success(function(data, status, headers, config) {
var anchor = angular.element('<a/>');
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'filename.csv'
})[0].click();
}).
error(function(data, status, headers, config) {
// handle error
});
Ответ 2
Большинство ссылок в Интернете об этой проблеме указывают на то, что вы не можете загружать файлы через ajax-вызов "из коробки". Я видел (хакерские) решения, которые включают iframes
, а также такие решения, как @dcodesmith, которые работают и являются абсолютно жизнеспособными.
Здесь другое решение, которое я нашел, работает в Angular и очень неудобно.
В представлении оберните кнопку загрузки csv
тегом <a>
следующим образом:
<a target="_self" ng-href="{{csv_link}}">
<button>download csv</button>
</a>
(Обратите внимание на target="_self
там, важно отключить маршрутизацию Angular внутри ng-приложения подробнее здесь)
Внутри контроллера вы можете определить csv_link
следующим образом:
$scope.csv_link = '/orders' + $window.location.search;
($window.location.search
является необязательным и onlt, если вы хотите передать дополнительный запрос на свой сервер)
Теперь каждый раз, когда вы нажимаете кнопку, она должна начинаться с загрузки.
Ответ 3
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it not visible
angular.element(document.body).append(anchor); // Attach to document
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'filename.csv'
})[0].click();
anchor.remove(); // Clean it up afterwards
Этот код работает как с Mozilla, так и с хромом
Ответ 4
Это то, что сработало для меня для IE 11+, Firefox и Chrome. В сафари он загружает файл, но неизвестен, и имя файла не задано.
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([csvDataString]); //csv data string as an array.
// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
window.navigator.msSaveBlob(blob, fileName);
} else {
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it not visible
angular.element(document.body).append(anchor); // Attach to document for FireFox
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(csvDataString),
target: '_blank',
download: fileName
})[0].click();
anchor.remove();
}
Ответ 5
Использование angular 1.5.9
Я сделал это так, установив window.location в URL-адрес загрузки файла csv. Протестировано и работает с последней версией Chrome и IE11.
Angular
$scope.downloadStats = function downloadStats{
var csvFileRoute = '/stats/download';
$window.location = url;
}
HTML
<a target="_self" ng-click="downloadStats()"><i class="fa fa-download"></i> CSV</a>
В php установите следующие заголовки для ответа:
$headers = [
'content-type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="export.csv"',
'Cache-control' => 'private, must-revalidate, post-check=0, pre-check=0',
'Content-transfer-encoding' => 'binary',
'Expires' => '0',
'Pragma' => 'public',
];