如何使用移动 Safari 下载数据客户端?

Posted

技术标签:

【中文标题】如何使用移动 Safari 下载数据客户端?【英文标题】:How to download data client-side with mobile Safari? 【发布时间】:2015-03-09 20:33:24 【问题描述】:

我知道在 SO 上已经存在很多与此类问题相关的问题,例如:

Create a file in memory for user to download, not through server Using html5/javascript to generate and save a file Data protocol URL size limitations Save file Javascript with file name Creating a Blob from a base64 string in JavaScript Failed to execute 'atob' on 'Window'

这个问题是针对 ios 8.1.3(移动设备、iPad 2+)上的 Safari 的。我们有一个使用 Application CacheIndexedDB 来存储数据的离线 AngularJS Web 应用程序。一种数据是可能相对较大的 PDF 文档:最大约 25 兆字节。我们将这些文件存储在 IndexedDB 中,当用户想要下载它时,我们使用 JavaScript 将这个文件保存在浏览器的内存中。

问题出在用户想要保存它的时候。 Safari Mobile 崩溃可能是由于 Data 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:文件数据,base 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);
;

【问题讨论】:

看看this question 和the answer。因为 ios 中的atob 在存在空格字符时会崩溃。 为什么需要使用base64?我问是因为当你使用时,文件会变大 37%。大约会大 37%:非常粗略,Base64 编码的二进制数据的最终大小等于原始数据大小的 1.37 倍来源:en.wikipedia.org/wiki/Base64 我有一个问题,它会破坏所有文件大小还是特定文件大小? 根据@ykaragol 的评论,base64 编码的字符串中会有空格吗? ***.com/questions/3092019/… @Marco 您的问题的答案在 ykaragol 的评论中 【参考方案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 及更低版本。

在 Safari 9 或更低版本中查看 https://visualstudio.microsoft.com/thank-you-downloading-visual-studio-mac/?sku=communitymac&rel=16# 以了解我所说的行为,其中 a 标签 href 更改为要下载的 URL一个文件。

让我知道这是否适合你!

【讨论】:

以上是关于如何使用移动 Safari 下载数据客户端?的主要内容,如果未能解决你的问题,请参考以下文章

如何使应用程序图标在下载时出现在客户端的移动应用程序中

如何使Safari和IE下载图像而不是在新页面中打开?

移动 safari (iOS) 中的 javascript 不会下载日历邀请

如何使应用程序键盘与 iPhone 中的 Safari 键盘相同?

如何使 <div> 完全填满浏览器窗口,包括截至 2019 年的 Mobile Safari

如何将 cookie 从我的 ios 应用程序共享到移动 safari?