需求:由于后台服务器各方面的限制,现在服务器返回的图片是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图片如何预览与一键保存到本地相册?的更多相关文章

  1. 微信小程序点击图片放大预览

    微信小程序点击图片放大预览使用到 wx.previewImage 接口,可以放大.上/下一张 上代码 wxml代码 <view class='content-img' wx:if="{ ...

  2. 微信小程序实战篇-图片的预览、二维码的识别

    开篇 今天,做的小程序项目要求,个人中心的客服图片在用户长按时可以识别其二维码,各种翻阅查找,采坑很多,浪费了很多时间,在这里记录下需要注意的点,以及对小程序官方提供的API做一个正确和清晰的认知,希 ...

  3. 微信小程序开发之真机预览

    1:真机预览时上传组件的坑: 当在真机里面使用上传组件,当进入选择相片或者拍照的时候,小程序会进入后台,调用APP onHide()方法,选择完返回小程序是会调用App Onshow()方法,然后调用 ...

  4. 微信小程序上传图片,视频及预览

    wxml <!-- 图片预览 --> <view class='preview-warp' wx:if="{{urls}}"> <image src= ...

  5. 微信小程序简单封装图片上传组件

    微信小程序简单封装图片上传组件 希望自己 "day day up" -----小陶 我从哪里来 在写小程序的时候需要上传图片,个人觉得官方提供的 Uploader 组件不是太好用, ...

  6. 微信小程序开发之图片预览

    实现图片的展示和大图预览 使用wx.previewImage(OBJECT)来实现 OBJECT参数说明: 参数 类型 必填 说明 current String 否 当前显示图片的链接,不填则默认为 ...

  7. 微信小程序——网盘图片预览

    微信小程序图片预览提供了一个wx.previewImage接口,如下图: 现在我需要对网盘文件里的图片预览,但是网盘从后台返回的数据是各种类型的文件,如下图所示: 那么我们需要解决2个问题: 1.从这 ...

  8. 微信小程序开发——base64位图片显示问题

    前言: 目前小程序项目需要后端借口提供验证码图片,后端是以base64位返回的,按照H5的做法,前边拼上 data:image/png;base64, 应该就可以了,关键代码如下: H5: <i ...

  9. 微信小程序——引入背景图片【六】

    前言 之前写了一些小程序的博文只是看文档边看边写,了解下他,这次可是真枪真刀的做了! 框架使用的是美团的mpvue,我也是一边学习,一边写的,如有错误之处,还望大家指出. 在这里我有个问题,为什么微信 ...

随机推荐

  1. 拿 C# 搞函数式编程 - 3

    前言 今天和某个人聊天聊到了 C# 的 LINQ,发现我认识的 LINQ 似乎和大多数人认识的 LINQ 不太一样,怎么个不一样法呢?其实 LINQ 也可以用来搞函数式编程. 当然,并不是说写几个 l ...

  2. 从 ASP.NET Core 3.1 迁移到 5.0

    3月中旬,微软官方已经发布了dotnet 5的第一个预览版:5.0.0-preview.1. dotnet core经过前几个版本的发展和沉淀,到3.1已经基本趋于稳定. 所以从.net core 3 ...

  3. 上Github,北大、清华、浙大、中科大4大名校课程在线学,加星总数超1.8万

    [导读]因为大学生找课程资料很麻烦,直到有人把搜集到的资料放在了Github上!现在,你不光都可以自由免费的获取北大.清华.浙大.中科大的相关课程资源进行自学,也可以对资源进行补充. 读过大学的人,对 ...

  4. DNS 域名解析

    DNS域名解析 整个过程大体描述如下,其中前两个步骤是在本机完成的,后8个步骤涉及到真正的域名解析服务器:1.浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就结束. ...

  5. java程序:转化金额

    在处理财务账款时,需要将转账金额写成大写的.也就是说,如果要转账123456.00元,则需要写成“壹拾贰万叁仟肆佰伍拾陆元整”.所以常常需要通过程序控制自动进行转换.本实例实现了小写金额到大写金额的转 ...

  6. 关于HashSet与HashMap

    package com.test; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; i ...

  7. ftp 无法显示远程文件夹

    翻阅了网上前辈们的答案,都未能解决,所以就研究了一下 不需要防火墙的情况,关闭防火墙即可 下面使用的iptables防火墙验证的,其他的请自行验证 研究了好久,发现ftp使用端口波动很大,大概在300 ...

  8. Codeforces Global Round 7

    A. Bad Ugly Numbers 思路 题意: 给我们一个k,让我们用 0-9 之间的数字构成一个 k位数a,a不能被组成a的每一位数字整除. 分析:首先 k等于1,无论我们怎么配都会被整除:当 ...

  9. Codeforces Round #565 (Div. 3)--D. Recover it!--思维+欧拉筛

    D. Recover it! Authors guessed an array aa consisting of nn integers; each integer is not less than ...

  10. RedHat 6.7 使用 CentOS 6 的源

    1. 移除 RedHat 相关软件包 # yum -y remove subscription-manager and rh-check # rpm -aq | grep yum | xargs rp ...