微信小程序之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,我也是一边学习,一边写的,如有错误之处,还望大家指出. 在这里我有个问题,为什么微信 ...
随机推荐
- 题解 P4344 【[SHOI2015]脑洞治疗仪】
前言 这道题目呢,看上去很难,实际上我们可以用线段树解决这道题目. 正文 我们维护 sum.len.tag.lmax.rmax.ans. sum 就是这段区间非脑洞的个数 len 就是这段区间的长度 ...
- 使用SlimYOLOv3框架实现实时目标检测
介绍 人类可以在几毫秒内在我们的视线中挑选出物体.事实上,你现在就环顾四周,你将观察到周围环境并快速检测到存在的物体,并且把目光回到我们这篇文章来.大概需要多长时间? 这就是实时目标检测.如果我们能让 ...
- 如何利用python实现为每行添加行数编号
可能还有更好的方法,在这里我是这么写的,针对小文件可以,但是如果文件内容太多,这种方法感觉不太好 先把所有的数据读取出来,然后利用W覆盖写入模式打开文件进行写入 遍历枚举类型数据后,默认是从0开始,然 ...
- Javascript/Jquery遇到字符串自动NaN的问题
结果发现是一个id绑定了两次点击事件.修改之后,问题解决.
- Java递归练习201908091049
package org.jimmy.autofactory.test; public class TestRecursive20190809 { public static void main(Str ...
- Python第三方包之pretty-errors
Python第三方包之pretty-errors 发现了一个第三方好用的python包,这个包可以让我们在面对冗长的错误时候能够一眼看到重点 安装方式 pip install pretty-error ...
- @RequestBody和@RequestParam的使用详解
此次分享转载至:https://blog.csdn.net/justry_deng/article/details/80972817 这边文章讲解的比较透彻,主要是在springboot项目中进行使用 ...
- Spring Boot创建一个HelloWorld项目
目录 Spring Boot 简介 微服务框架 以前使用spring开发web的方式 Spring Boot 启动器介绍 如何创建一个helloword的SpringBoot项目 Spring Boo ...
- NKOJ3765 k个最小和
问题描述 有k个整数数组,各包含k个元素,从每个数组中选取一个元素加起来,可以得到k^k个和,求这些和中最小的k个值. 输入格式 第一行,一个整数k(k<=500)接下来k行,每行k个正整数(& ...
- 使用Azure Functions 在web 应用中启用自动更新(一)分析基于轮询的 Web 应用的限制
1,引言 上一篇介绍了使用使用 Visual Studio 开发 "Azure Functions" 函数,此篇介绍 “Azure Functions” 的测试以及直接从 Vist ...