微信小程序之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="{{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 = this
let token = that.data.scanToken
let iData = {
currentNumber: that.data.currentPage
}
var i = 0
let handerRequest = setInterval(function() {
// 发送请求
i++;
util.request(api.DownloadImgsList, iData, 'POST', token).then(function(res) {
if (i === 60) {
clearInterval(handerRequest)
let number = that.data.currentPage - 1
console.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 = new Array(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 - 1
that.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);
return item;
}, [])
},
// 图片排序
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 = 0
let 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 = this
let 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图片如何预览与一键保存到本地相册?的更多相关文章
- 微信小程序点击图片放大预览
微信小程序点击图片放大预览使用到 wx.previewImage 接口,可以放大.上/下一张 上代码 wxml代码 <view class='content-img' wx:if="{ ...
- 微信小程序实战篇-图片的预览、二维码的识别
开篇 今天,做的小程序项目要求,个人中心的客服图片在用户长按时可以识别其二维码,各种翻阅查找,采坑很多,浪费了很多时间,在这里记录下需要注意的点,以及对小程序官方提供的API做一个正确和清晰的认知,希 ...
- 微信小程序开发之真机预览
1:真机预览时上传组件的坑: 当在真机里面使用上传组件,当进入选择相片或者拍照的时候,小程序会进入后台,调用APP onHide()方法,选择完返回小程序是会调用App Onshow()方法,然后调用 ...
- 微信小程序上传图片,视频及预览
wxml <!-- 图片预览 --> <view class='preview-warp' wx:if="{{urls}}"> <image src= ...
- 微信小程序简单封装图片上传组件
微信小程序简单封装图片上传组件 希望自己 "day day up" -----小陶 我从哪里来 在写小程序的时候需要上传图片,个人觉得官方提供的 Uploader 组件不是太好用, ...
- 微信小程序开发之图片预览
实现图片的展示和大图预览 使用wx.previewImage(OBJECT)来实现 OBJECT参数说明: 参数 类型 必填 说明 current String 否 当前显示图片的链接,不填则默认为 ...
- 微信小程序——网盘图片预览
微信小程序图片预览提供了一个wx.previewImage接口,如下图: 现在我需要对网盘文件里的图片预览,但是网盘从后台返回的数据是各种类型的文件,如下图所示: 那么我们需要解决2个问题: 1.从这 ...
- 微信小程序开发——base64位图片显示问题
前言: 目前小程序项目需要后端借口提供验证码图片,后端是以base64位返回的,按照H5的做法,前边拼上 data:image/png;base64, 应该就可以了,关键代码如下: H5: <i ...
- 微信小程序——引入背景图片【六】
前言 之前写了一些小程序的博文只是看文档边看边写,了解下他,这次可是真枪真刀的做了! 框架使用的是美团的mpvue,我也是一边学习,一边写的,如有错误之处,还望大家指出. 在这里我有个问题,为什么微信 ...
随机推荐
- 第十六周Java实验作业
实验十六 线程技术 实验时间 2017-12-8 1.实验目的与要求 (1) 掌握线程概念: 多线程是进程执行过程中产生的多条执行线索,线程是比进程执行更小的单位. 线程不能独立存在,必须存在于进程 ...
- [AI开发]零代码公式让你明白神经网络的输入输出
这篇文章的标题比较奇怪,网上可能很少类似专门介绍神经网络的输入输出相关文章.在我实际工作和学习过程中,发现很有必要对神经网络的输入和输出做一个比较全面地介绍.跟之前博客一样,本篇文章不会出现相关代码或 ...
- Java井字棋游戏
试着写了一个井字棋游戏,希望各位能给予一些宝贵的建议. 一.棋盘类 package 井字棋游戏; public class ChessBoard { private int number; Perso ...
- IdentityServer4源码解析_5_查询用户信息接口
协议简析 UserInfo接口是OAuth2.0中规定的需要认证访问的接口,可以返回认证用户的声明信息.请求UserInfo接口需要使用通行令牌.响应报文通常是json数据格式,包含了一组claim键 ...
- 面试刷题25:jvm的垃圾收集算法?
垃圾收集是java语言的亮点,大大提高了开发人员的效率. 垃圾收集即GC,当内存不足的时候触发,不同的jvm版本算法和机制都有差别. 我是李福春,我在准备面试,今天的问题是: jvm的垃圾回收算法有哪 ...
- Oracle数据库的创建表全
CREATE TABLE "库名"."表名" ( "FEE_ID" VARCHAR2(10 BYTE) constraint ABS_FEE ...
- coding++:error 阿里云 Redis集群一直Waiting for the cluster to join....存在以下隐患
1):Redis集群一直Waiting for the cluster to join... 再次进行连接时首先需要以下操作 1.使用redis desktop Manager连接所有节点 调出命令窗 ...
- ESPCMS-Seay自动加手工代码审计
ESPcms代码审计 源码下载地址:http://yesky.91speed.org.cn/sw/180001_190000/rar/espcms_utf8_5.4.12.05.14.rar 1.自动 ...
- Word文档转html并提取标题
最近做了一个功能,需要将word文档转化成html的格式,并提取出标题生成导航.考虑到功能的复杂程度,将需要降低为对“标题1”这种格式进行提取. docx为后缀的文档(word2007)支持XML的文 ...
- [vios1023]维多利亚的舞会3<强联通分量tarjan>
题目链接:https://vijos.org/p/1023 最近在练强联通分量,当然学的是tarjan算法 而这一道题虽然打着难度为3,且是tarjan算法的裸题出没在vijos里面 但其实并不是纯粹 ...