微信小程序之base64图片如何预览与一键保存到本地相册?

摘要:
需求:由于后台服务器各方面的限制,现在服务器返回的图片是base64格式的,小程序端需要支持预览图片和多个图片一键下载功能一、如何预览base64位图片?=''){letsystem=that.data.system.substring(0,3)console.logif{console.log}else{leturl='data:image/png;base64,'+e.currentTarget.dataset.srcwx.previewImage}}},二、一键下载多张base64位的图片?如果图片请求到则展示图片,如果请求不到,则在页面显示占位图片,且点击该图片需重新发送请求该图片的接口。

需求:由于后台服务器各方面的限制,现在服务器返回的图片是base64格式的,小程序端需要支持预览图片和多个图片一键下载功能

一、如何预览base64位图片?

WXML页面:item.src的值是base64编码的字符串

 <block wx:for="{{imgsLength}}" wx:key="index">
      <image mode="widthFix" bindtap="preImg" src="data:image/png;base64,{{item.src}}" data-src="http://t.zoukankan.com/{{item.src}}"></image>
  </block>

JS: 由于ios13和微信7.0.12匹配有问题,导致预览图片的时候使得微信闪退

//图片预览
preImg(e) {
    let that = this
    if (that.data.system != '') {
      let system = that.data.system.substring(0, 3)
      console.log('system: ', system.toLowerCase())
      if (system.toLowerCase() == 'ios') {
        console.log('当前系统不支持预览')
      } else{
        let url = 'data:image/png;base64,' +e.currentTarget.dataset.src
        wx.previewImage({
          current: url, //当前显示图片的http链接
          urls: [url] //需要预览的图片http链接列表
})
      }
    }
  },

二、一键下载多张base64位的图片?

需求:(1)由于后台服务器的限制,现只能一张一张请求图片,且每隔1s请求一次接口,每张图片总共请求60次。(2)如果图片请求到则展示图片,如果请求不到,则在页面显示占位图片,且点击该图片需重新发送请求该图片的接口。

步骤一:页面加载开始就请求第一张图片,当第一张图片返回后或者请求次数已达上限,则请求下一张。

//请求图片
getImgsList() {
    let that = thislet token =that.data.scanToken
    let iData ={
      currentNumber: that.data.currentPage
    }
    var i = 0let handerRequest = setInterval(function() {
      //发送请求
      i++;
      util.request(api.DownloadImgsList, iData, 'POST', token).then(function(res) {
        if (i === 60) {
          clearInterval(handerRequest)
          let number = that.data.currentPage - 1console.log('失败图片是第' + number + '页')
          that.setData({
            ['imgsLength[' + number + '].requestNum']: i,
          })
          //查询下一个
that.getNextImg()
        }
        if (res.data.code === 0) {
          clearInterval(handerRequest)
          if (!that.data.totalNumber &&res.data.data.totalNumber) {
            console.log('图片总数----', res.data.data.totalNumber)
            log.info('图片总数----', res.data.data.totalNumber)
            that.setData({
              totalNumber: res.data.data.totalNumber, //图片总数
})
            //图片占位数组
            let imgsLength = newArray(res.data.data.totalNumber).fill({
              'src': '',
              'number': '',
              'requestNum': ''})
            that.setData({
              imgsLength: imgsLength,
            })
          }
          if (res.data.data.currentNumber &&res.data.data.file) {
            let imgsArr =[]
            imgsArr.push({
              'src': res.data.data.file,
              'number': res.data.data.currentNumber
            })
            that.setData({
              imgs: that.reduce(that.data.imgs.concat(imgsArr).sort(that.arraySort('number')), 'number'),
            })
            that.data.imgsLength.find((item, index) =>{
              if ((index + 1) ==res.data.data.currentNumber) {
                let num =index
                that.setData({
                  ['imgsLength[' + index + '].src']: res.data.data.file,
                  ['imgsLength[' + index + '].number']: res.data.data.currentNumber,
                })
              }
            })
          }
          //查询下一个
that.getNextImg()
        } else if (res.data.code === 59706) {
          console.log('getImgs res: ', res)
          clearInterval(handerRequest)
          wx.showToast({
            icon: 'none',
            title: 'token失效,请重新扫码',
          })
        } else{
          console.log('请求图片错误', res)
        }
      }).catch(err =>{
        if (i === 60) {
          clearInterval(handerRequest)
          let number = that.data.currentPage - 1that.setData({
            ['imgsLength[' + number + '].requestNum']: i,
          })
          //查询下一个
that.getNextImg()
        }
        console.log("请求图片err:", err);
      });
    }, 1000)
  },
  //获取下一个图片
getNextImg() {
    let that = this
    if (that.data.currentPage + 1 <=that.data.totalNumber) {
      that.setData({
        currentPage: that.data.currentPage + 1})
      that.getImgsList()
    } else{
      console.log('没有更多图片')
    }
  },

注意:由于异步可能会使得返回的图片有重复的或者不是按照请求的顺序返回的,因此需要对图片进行去重和排序

//图片去重
reduce(arr, name) {
    var hash ={}
    return arr.reduce(function(item, next) {
      hash[next[name]] ? '' : hash[next[name]] = true &&item.push(next);
      returnitem;
    }, [])
  },
  //图片排序
arraySort(field) {
    return function(obj1, obj2) {
      let a =obj1[field]
      let b =obj2[field]
      return a -b
    }
  },

如何重新加载之前失败的图片:

//重新加载
loadAgain (e) {
    let that = this;
    let number =e.currentTarget.dataset.index
    //点击重新加载当前图片
    let token =that.data.scanToken
    let iData ={
      currentNumber: number + 1}
    var i = 0let handerRequest = setInterval(function() {
      //发送请求
      i++;
      util.request(api.DownloadImgsList, iData, 'POST', token).then(function(res) {
        if (i === 60) {
          clearInterval(handerRequest)
        }
        if (res.data.code === 0) {
          clearInterval(handerRequest)
          if (res.data.data.currentNumber &&res.data.data.file) {
            let imgsArr =[]
            imgsArr.push({
              'src': res.data.data.file,
              'number': res.data.data.currentNumber
            })
            that.setData({
              ['imgsLength[' + number + '].src']: res.data.data.file,
              ['imgsLength[' + number + '].number']: res.data.data.currentNumber,
              imgs: that.reduce(that.data.imgs.concat(imgsArr).sort(that.arraySort('number')), 'number'),
              totalNumber: res.data.data.totalNumber, //图片总数
})
          }
        } else if (res.data.code === 59706) {
          console.log('loadAgain res: ', res)
          clearInterval(handerRequest)
          wx.showToast({
            icon: 'none',
            title: 'token失效,请重新扫码',
          })
        } else{
          console.log('请求图片错误', res)
        }
      }).catch(err =>{
        if (i === 60) {
          clearInterval(handerRequest)
        }
        console.log("请求图片err:", err);
      });
    }, 1000)
  },

步骤二:至此,需要下载的图片已经存进了imgs数组中。由于小程序无法直接将base64的图片直接保存到本地相册,因此需要先将文件写入本地,之后再进行保存到相册的操作。

1.由于微信小程序限制,小程序文件系统写入文件,大小最多是10m,在ios上测试的时候发现writeFile报错,为了规避这个问题,我在写入文件的时候会先清理之前的文件。
//下载
download() {
    let that = this
    if (that.data.imgs.length > 0 && that.data.imgs.length ==that.data.imgsLength.length) {
      //先创建一个保存图片的本地文件目录
      let fs =wx.getFileSystemManager()
      //再判断takeAway目录是否存在,不存在则新建该目录
fs.access({
        path: `${wx.env.USER_DATA_PATH}/takeAway`,
        success: res =>{
          console.log('takeAway目录存在res:', res)
          log.info('takeAway目录存在res:', res)
          that.dow_temp(0)
        },
        fail: err =>{
          console.log('takeAway目录不存在:', err)
          log.info('takeAway目录不存在:', err)
          fs.mkdir({
            dirPath: `${wx.env.USER_DATA_PATH}/takeAway`,
            success: res =>{
              console.log('创建保存图片的本地文件路径成功', res)
              log.info('创建保存图片的本地文件路径成功', res)
              that.dow_temp(0)
            },
            fail: err =>{
              console.log('创建保存图片的本地文件路径失败', err)
              log.error('创建保存图片的本地文件路径失败', err)
            }
          })
        }
      })
    } else{
      wx.showToast({
        icon: 'none',
        title: '图片还未完全加载完毕,请稍后再试!',
        duration: 3000})
    }
  },
  //下载单个内容
  dow_temp: function(i, callback) {
    let that = this
    var fs =wx.getFileSystemManager()
    //先删除之前takeAway目录下的文件
    return new Promise((resolve) =>{
      fs.readdir({
        dirPath: `${wx.env.USER_DATA_PATH}/takeAway`,
success(res) {
          res.files.forEach((el) =>{
            fs.unlink({
              filePath: `${wx.env.USER_DATA_PATH}/takeAway/${el}`,
              fail(e) {
                console.log('readdir文件删除失败:', e)
              }
            })
          })
          resolve(that.saveImgFile(i, callback))
        }
      })
    })
  },

步骤三:图片保存

//图片保存
  saveImgFile: function(i, callback) {
    let that = thislet data =that.data.imgs
    let all_n =data.length
    if (i <all_n) {
      wx.authorize({
        scope: 'scope.writePhotosAlbum',
        success() {
          var fs =wx.getFileSystemManager();
          var number =Math.random();
          const downloadTask =fs.writeFile({
            filePath: `${wx.env.USER_DATA_PATH}/takeAway/${number}.png`,
            data: data[i].src,
            encoding: 'base64',
            success: res =>{
              wx.saveImageToPhotosAlbum({
                filePath: `${wx.env.USER_DATA_PATH}/takeAway/${number}.png`,
                success: function(res) {
                  wx.showToast({
                    icon: 'none',
                    title: `第${i + 1}/${all_n}张保存到系统相册`,
})
                  that.dow_temp(i + 1);
                },
                fail: function(err) {
                  console.info('第', (i + 1), '张保存失败');
                }
              })
            },
            fail: err =>{
              wx.showToast({
                title: '一键保存失败,请点击图片手动保存!',
                icon: 'none',
              })
            }
          })
        },
        fail: function() {
          wx.showToast({
            title: '获取授权失败',
            icon: 'none',
          })
        }
      })
    }
  },

免责声明:文章转载自《微信小程序之base64图片如何预览与一键保存到本地相册?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vim使用(转)A星寻路算法入门(Unity实现)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

base64的编码解码的一些坑

1、 //编码 value = base64encode(utf16to8(src)) //解码 value = utf8to16(base64decode(src))这里:base64编码之前先转成utf8,解码出来的也要从utf-8转为utf-16 2、base64编码分为字符串编码成字符串,字符串编码成数组,字符串解码成数组,字符串解码成字符串,等...

『MXNet』第八弹_数据处理API_下_Image IO专题

想学习MXNet的同学建议看一看这位博主的博客,受益良多。 在本节中,我们将学习如何在MXNet中预处理和加载图像数据。 在MXNet中加载图像数据有4种方式。 使用 mx.image.imdecode 加载原始数据文件 使用在Python中实现的mx.img.ImageIter ,很方便自定义。 它可以从.rec(RecordIO)文件和原始图像文件读...

python websocket Django 实时消息推送

概述: WebSocket 是什么? WebSocket 是 HTML5 提供的一种浏览器与服务器间进行全双工通讯的协议。依靠这种协议可以实现客户端和服务器端 ,一次握手,双向实时通信。 WebSocket 服务端: 用的是 dwebsocket,安装命令pip installdwebsocket. WebSocket 基本方法: 1.request.i...

postman 发送post请求,参数为json

mvc 控制器接收post请求,参数为json PostMan设置 Headers设置key和Value值 key:Content-Type,Value:application/json。 参数设置: 选中Body并进行参数设置,选择raw,格式为json。就酱 控制器代码: //post 请求测试 [HttpPost] //请求方法,...

JavaScript单元测试工具-Jest

标注: 首先这并不是一篇完整的关于Jest的教程,只是个人在接触jest学习的一点随手笔记,大部分内容都是对官方文档的一些翻译。 ------------------------------------------------------------------------------------------------------------------...

echarts-JSON请求数据

1、问题背景      将数据封装在JSON文件中,利用get方法请求数据 2、实现源码 <script> layui.use(['layer', 'echarts'], function () { var $ = layui.jquery, layer = layui.layer,...