Как показать диалог сохранения файла в Safari?
Мне нужна помощь. У меня есть приложение angular и с помощью DocRaptor вы хотите создать PDF файл и сохранить его как файл. Но я не могу запустить диалог для сохранения файла в Safari любым способом, который я нашел в Stack Overflow. Эти методы открывают файл на текущей вкладке браузера и заменяют сайт html или открывают файл на новой вкладке. Никто не может показать диалог. Вот примеры, которые я уже пытался использовать. Окружающая среда MacOS - EL Capitan. Safari 9.0.3
Решение # 1
var content = 'file content for example';
var blob = new Blob([ content ], { type : 'text/plain' });
$scope.url = (window.URL || window.webkitURL).createObjectURL( blob );
Пример jsfiddle. Показывает файл на текущей вкладке. Заменяет сайт. Но работает в Chrome.
Решение # 2
<a target="_self" href="mysite.com/uploads/ahlem.pdf" download="foo.pdf">
Пример jsfiddle. Не работает вообще в Safari. Работает в Chrome.
Решение # 3
<a class="btn" ng-click="saveJSON()" ng-href="{{ url }}">Export to JSON</a>
и
$scope.saveJSON = function () {
$scope.toJSON = '';
$scope.toJSON = angular.toJson($scope.data);
var blob = new Blob([$scope.toJSON], { type:"application/json;charset=utf-8;" });
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',window.URL.createObjectURL(blob));
downloadLink.attr('download', 'fileName.json');
downloadLink[0].click();
};
Пример фрагмент кода. Показывает содержимое файла вместо документа html.
Решение # 4
function download(text, name, type) {
var a = document.getElementById("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
}
Пример фрагмент кода. Замените документ содержимым файла в Safari. Работает в Chrome.
И подобное Решение # 5
function download(text, name, type) {
var a = document.createElement("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
a.click();
}
Пример jsfiddle. Не работает вообще в Safari. Работает в Chrome.
Также я попытался использовать библиотеки вроде:
FileSaver - он открывает файл в Safari вместо документа. Поэтому вы должны нажать Cmd + S. Пример.
Если мы используем тип "pplication/octet-stream", имя файла будет неизвестно или возникла ошибка "Не удалось загрузить ресурс: загрузка кадра прерывается". Issue.
Вторая библиотека Downloadify - вообще не работает в Safari. Issue.
Angular library nw-fileDialog - вместо сохранения, поскольку он показывает файл выбора. Issue.
DocRaptor имеет собственный пример с jQuery.
Пример с angular в jsfiddle. Он работает в Chrome, но в примере Safari не может быть причиной ошибки с SAMEORIGIN
Отказано в отображении 'https://docraptor.com/docs' в кадре, потому что он установил 'X-Frame-Options' в 'SAMEORIGIN'.
Но если мы воспроизведем его на сервере и изменим url на 'https://docraptor.com/docs.pdf', он работает и открывает файл на новой вкладке и автоматически загружает файл, поэтому вы не можете выбрать папку, и после того, как пользователь загрузки увидит белый пустой экран в браузере. Если мы укажем форму target = "_ self", она будет работать идеально, но консоль будет иметь ошибку "Не удалось загрузить ресурс:".
Буду признателен за любую помощь в решении этой проблемы.
Благодарю.
С наилучшими пожеланиями.
Ответы
Ответ 1
Попробуйте использовать Blob файл для этого:
// Buffer can be response from XMLHttpRequest/Ajax or your custom Int32 data
function download(buffer, filename) {
var file = new Blob([buffer], {
type: 'application/octet-stream' // Replace your mimeType if known
});
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var converted = e.target.result;
converted.name = filename;
converted.webkitRelativePath = filename;
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.src = converted;
};
fileReader.onerror = function(e) {
throw new Error('Something is wrong with buffer data');
};
fileReader.file = file;
fileReader.readAsDataURL(file);
}
В основном он использует filebuffer и загружает его как содержимое iframe. Обязательно подключите правильный тип mime, чтобы система безопасности Safari получала аналитический тип файла.
Ответ 2
В идеале решение №2 было бы ответом, но атрибут загрузки пока не поддерживает кросс-браузер.
Поэтому для создания загрузки вам необходимо использовать <form>
. Как вы отметили, DocRaptor пример jQuery использует эту технику.
Ошибка SAMEORIGIN на самом деле потому, что JSFiddle запускает код в iFrame с настройками источника. Если вы запускаете это прямо из своего приложения Angular, у вас не должно быть никаких проблем.