Как загрузить данные на стороне клиента с помощью мобильного Safari?

Я знаю, что существует много вопросов, уже существующих на SO, связанных с этой проблемой, например:

Этот вопрос очень специфичен для Safari на iOS 8.1.3 (Mobile, iPad 2+). У нас есть автономное веб-приложение AngularJS, использующее Application Cache и IndexedDB для хранения данных. Один вид данных - это документы PDF, которые могут быть относительно большими: максимум 25 мегабайт. Мы сохраняем эти файлы в IndexedDB, и когда пользователь хочет его загрузить, у нас есть этот файл в памяти в браузере с JavaScript.

Проблема в том, когда пользователь хочет ее сохранить. Ошибка Safari Mobile может быть связана с ограничением размера URI данных или чем-то еще.

this.save = function (file) {
    var mediaType = "application/pdf";

    var link = document.createElement("a");
    var blob = new Blob([this.fromBase64ToBinary(file.content)], { type: mediaType });

    var blobUrl = URL.createObjectURL(blob);
    document.body.appendChild(link);
    link.download = file.name;
    link.href = blobUrl;
    link.click();
    document.body.removeChild(link);
};

В службе у нас есть функция save(file), где file - объект, содержащий два свойства:

  • name: имя файла;
  • content: данные файла, который кодируется базой 64, затем преобразуем его в двоичный.

Функция atob() может быть причиной? Когда я делаю пошаговую отладку на iPad, запускающем этот код, он падает прямо там (то есть: строка с var byteCharacters = atob(b64Data);).

this.fromBase64ToBinary = function (base64) {
    var byteCharacters = atob(base64);
    var byteNumbers = new Array(byteCharacters.length);
    for (var i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }

    return new Uint8Array(byteNumbers);
};

Ответ 1

Я имел дело с аналогичной проблемой. То, как я решил это было так:

// Detects if Safari 9 or less
var isSafariNineOrLess = navigator.vendor && navigator.vendor.indexOf('Apple') 
> -1 &&
navigator.userAgent &&
navigator.userAgent.indexOf('CriOS') === -1 &&
navigator.userAgent.indexOf('FxiOS') === -1 &&
window.ApplePaySession === undefined;

...

if(!isSafariNineOrLess) {
    save(file);
}
else {
   var myLink = document.getElementById('myLink');
       if(myLink) {
          myLink.removeAttribute('href');
          myLink.setAttribute('href', 'http://example.com/download.pdf.zip');
        }
 }

Затем, когда люди нажимают на ссылку, они могут скачать заархивированный файл, содержащий PDF. Похоже, вы используете https://github.com/eligrey/FileSaver.js или что-то подобное, и это абсолютно не работает с Safari 9 и ниже.

Посмотрите на https://visualstudio.microsoft.com/thank-you-downloading-visual-studio-mac/?sku=communitymac&rel=16# в Safari 9 или ниже поведения я говорю о том, где а тег href заменен на URL для загрузки файла.

Дайте мне знать, если это работает для вас!