目前在手机微信浏览器中打开的 H5 页面,是无法通过 JavaScript 的 API 实现图片或文件下载的。
为什么在手机的默认浏览器就可以下载,但我们在微信里面打开浏览器,就下不了了呢?
我觉得是微信 APP 的权限问题,下载的权限是掌握在当前使用的 APP 手上的。微信拒绝了内置浏览器的下载文件请求,即使浏览器自身有对应的下载 API,但你就是下载不了。
微信为什么这么做?是因为怕以前常见的浏览器弹窗广告一样的情况出现。如果对图片下载权限不做限制的话,很多搞营销的就会诱导用户打开一些网页,然后自动下载一些广告宣传图片之类的东西。
但长按图片保存还是可以的。
但也不是完全没办法,微信还是提供了一些 API 来实现 受限 的下载功能。
使用微信的 JS-SDK
我们可以使用微信提供的 JS-SDK 去和微信通信,获得一些手机系统的能力。
官方说法为:
微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。
用法就是在页面引入这个 jssdk 的 js 文件,然后你就能拿到一个 wx 的对象。然后调用 config 方法,传入 appId、签名等信息(这个需要在微信公众号平台获取)。之后我们就可以通过 wx 对象的方法去和微信通信,使用手机系统的能力。
其中有个 wx.downloadImage()
的方法,是用来下载图片的。但其实我觉得应该是用来耍猴的。
该方法不接受一个 url 参数,而是接受一个 serverId。
serverId 从哪来,从另一个方法 wx.uploadImage()
里面获得。wx.uploadImage()
方法用于上传本地的图片,但上传成功后,回调函数就能拿到一个 serverId。
上传到哪?微信自己的服务器。如果你想保存到自己公司的服务器,你还得让公司服务器调用多媒体接口,从微信服务器拿回图片。而且,微信服务器只给你保存 3 天时间
是的,你能下载的图片的图片来自用户的上传,且只有三天有效期。另外,下载的图片貌似也不会保存到相册里,而是保存在用户找不到的地方。
结论就是完全没法用。
微信小程序
小程序提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在微信中开发具有原生 APP 体验的服务。
微信小程序算不上是 H5,因为它是微信下的原生程序,只是语法上类似网页开发的那一套。
微信小程序的 Hello World 项目模板的入口文件为下面代码。
// app.ts App<IAppOption>({ globalData: {}, onLaunch() { // 展示本地存储能力 const logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录 wx.login({ success: res => { console.log(res.code) // 发送 res.code 到后台换取 openId, sessionKey, unionId }, }) }, })
可以看到,这里同样有一个 wx 对象。
但需要注意的是,这个 wx 对象和 JS-SDK 的 wx 是完全不同的东西,千万别混为一谈。
调用 wx.downloadFile()
方法并传入一个 url 就能下载文件。但有一些限制,比如单次下载大小最大为 200 MB、只能访问开发设置配置好的指定域名、域名需 ICP 备案等。
下载的文件会保存在一个本地临时路径。如果是图片,可以再调用 wx.saveImageToPhotosAlbum()
方法保存到相册。
讲了半天,这个微信小程序也不是 H5 啊,如果我的微信小程序通过 web-view
元素嵌入了一个 H5 页面,那我这个 H5 页面是不是会更牛逼一点,是不是可以用小程序的 wx 对象啊。
不行。
尽管是内嵌的 H5 页面,但其实它和小程序是隔离的,小程序内嵌的 H5 页面其实和普通的 H5 页面没有区别,还是得用傻不拉几的 JS-SDK。
讲这么多,主要是想让大家认识到:wx.downloadFile() 是微信小程序才能使用的,不可以用到 H5 上,即使这个 H5 是内嵌到小程序里的。
话说回来,为什么微信小程序的能力要比 JS-SDK 受到的限制小很多呢?
我认为是因为开发者开发的微信小程序是受到微信监管的,发布也需要通过微信的审核,微信也有权限将任何小程序下架。
所以微信不怕小程序开发者滥用功能,抓到了直接就给你封了。而用 H5 页面则是完全开放的,
那么方案是?
首先,微信浏览器中的 H5 页面,我们无法让用户通过点击 “下载” 按钮来下载图片、视频以及文档文件(pdf、word 等),而是打开一个新的页面让你预览。
但对于其他微信不能预览的文件(如果 zip 压缩包)来说,则会将其下载下来。
但是对于展示出来的图片,用户可以长按图片保存下来。
所以我们的常规方案是:
首先要判断浏览器是否为微信浏览器,如果不是微信浏览器,下载保持原来逻辑。
如果是图片,点击下载按钮时弹出弹窗,提示用户长按图片下载;
如果是视频或文档文件,提示用户使用默认浏览器去下载文件。考虑到用户用新的浏览器又要登陆很麻烦,引导用户点击右上角将链接用默认浏览器打开并不是好方案。
我们可以在点击下载按钮时,复制文件链接,然后让用户自行打开默认浏览器粘贴链接下载。这种占用用户剪贴板的行为其实不太好。
或者直接将下载按钮屏蔽掉算了,又或是弹出只能在 PC 端下载的提示。
如果是其他类型文件,倒是可以下载。
结尾
今天讲了微信浏览器不能下载图片的一些原因,误解和解决方案,希望对你有所帮助。
我是前端西瓜哥,欢迎关注我。