需求:由于后台服务器各方面的限制,现在服务器返回的图片是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. Ubuntu环境下部署Django+uwsgi+nginx总结

    前言 这是我在搭建Django项目时候的过程,拿来总结记录,以备不时之需. 项目采用nginx+uwsgi的搭配方式. 项目依赖包采用requirements.txt文件管理的方式. 本地准备工作 确 ...

  2. 【干货】史上最全的Tensorflow学习资源汇总

    欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 作者:AI小昕 在之前的Tensorflow系列文章中,我们教大家 ...

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

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

  4. Error response from daemon: rpc error: code = AlreadyExists desc = name conflicts with an existing object: service myweb already exists

    主机环境 centos7.2 执行 docker service create --replicas 6 --name myweb -p 80:80 nginx:latest 时 报 Error re ...

  5. spring5之容器始末源码赏析 (一)总览

    首先,本系列并不是以介绍spring5 的新特性为主,之所以以spring5为标题,是因为即将赏析的源码来自最新的spring版本.虽说是spring最新版本,但是容器的整个生命周期与之前版本相比,并 ...

  6. 《java编程思想》对象导论

    1.抽象过程 所有编程语言都提供抽象机制.可以认为,人们所能够解决的问题的复杂性直接取决于抽象的类型和质量,所谓的'类型'是指“所抽象的是什么?”汇编语言是对底层机器的轻微抽象. java的基本 特性 ...

  7. .Net微服务实践(一):微服务框架选型

    微服务框架 微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署,各个微服务之间是松耦合的.每个微服务仅关注于完成一件任务并很 ...

  8. 使用nginx访问FastDFS

    文中所有~~~均为同一个自定义文件夹名字,一般使用项目名称 2.1.为什么需要用Nginx访问? FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组存储服务器之间需要 ...

  9. vue3.0+axios 跨域+封装

    封装: 目录结构:src/utils/request.js, 没有就自己建一个 //src/utils/request.jsimport axios from 'axios' import { Mes ...

  10. B 雷诺与奴隶主

    时间限制 : 5000 MS   空间限制 : 524288 KB 问题描述 自从周文武老师在班上吹嘘了"录试"这款游戏之后,PHD同学沉迷于其中无法自拔. "录试&qu ...