微信小程序保存图片功能

1,544 阅读1分钟

背景

最近产品提了一个小程序保存图片的功能。小程序预览本来是支持长按图片保存的,但是考虑到部分用户不知道这个功能,只能单做一个保存图片的按钮。

问题

保存图片的功能看起来是很简单的。但我做的时候遇到了下面几个问题。

  • 图片url

wx.saveImageToPhotosAlbum方法只支持保存本地路径,不支持网络路径,需要使用wx.downloadFile下载文件资源到本地,取到图片本地路径。

  • 兼容性问题

兼容性问题指的是,我们项目的要保存的图片是一个GET接口地址,返回图片的文件流,这样它的url就不是标准的png/jpg后缀格式,经试验,在微信开发者工具和苹果手机上都可以保存,但在安卓手机上会报错,“saveImageToPhotosAlbum:fail invalid file type”,其实就是图片类型错误。我们可以在wx.downloadFile时加上filePath属性,手动加上图片后缀。代码如下所示:

saveImageToPhotosAlbum() {
    const that = this;
    wx.downloadFile({
      url: this.qrCode,
      filePath: `${wx.env.USER_DATA_PATH}/${Date.now()}.jpg`,
      success(result) {
        wx.saveImageToPhotosAlbum({
          filePath: result.filePath,
          success(res) {
            that.$toast('图片保存成功', 'success');
          },
          fail(err) {
            console.log(err);
            that.$toast('图片保存失败');
          }
        });
      }
    });
}
  • 授权问题

在保存图片时小程序会发起「保存图片」授权。我们需要判断三种情况:未授权、拒绝授权和授权成功。可以使用wx.getSetting方法获取到用户的授权情况。代码如下:

saveImageEvent() {
  const settingId = 'scope.writePhotosAlbum';
  getAuthSetting('authSetting', settingId).then(writePhotosAlbum => {
    const that = this;
    console.log('writePhotosAlbum', writePhotosAlbum);
    if (writePhotosAlbum === undefined) { // 未授权过,申请授权
      wx.authorize({
        scope: settingId,
        success() {
          that.saveImageToPhotosAlbum();
        },
        fail(res) {
          that.$toast('授权失败');
        }
      });
    } else if (writePhotosAlbum === false) { // 拒绝授权,打开授权设置
      wx.openSetting({
        success(res) {
          if (res.authSetting[settingId]) {
            that.saveImageToPhotosAlbum();
          }
        },
        fail() {
          that.$toast('授权失败');
        }
      });
    } else {
      this.saveImageToPhotosAlbum();
    }
  });
}


/**
 *  获取用户权限设置
 * @param {*} settingType 设置类型:authSetting、subscriptionsSetting
 * @param {*} settingId 设置ID:address、writePhotosAlbum等
 */
export function getAuthSetting(settingType, settingId) {
  return new Promise((resolve, reject) => {
    wx.getSetting({
      withSubscriptions: true,
      success(response) {
        console.log(response);
        resolve(response[settingType][settingId]);
      }
    });
  }).catch(res => {
    console.log(res);
  });
}

参考文章:https://juejin.cn/post/6844904166070943751