赞
踩
原有项目使用Vue框架和Element组件库,图片展示和下载功能可细分为:
1. 图片展示是将单个图片点击后,弹窗显示,用户选择保存则以服务端id命名保存至本地;
2.下载功能分为单个图片下载和批量下载
原有管理系统中增加上述功能,需要新增JSZip和FileSaver两个JS库,开发步骤如下:
安装JSZip和FileSaver
- npm install jszip --save
- npm install file-saver --save
JSZip 库用于处理和生成 ZIP 文件。主要用到该库中两个方法:
file
()是 JSZip
对象的一个方法,用于向 ZIP 文件中添加文件。它接受两个参数:要添加到 ZIP 文件中的文件名和文件内容;generateAsync()
用于异步生成 ZIP 文件。它返回一个 Promise,该 Promise 在 ZIP 文件生成完成后被解析。方法使用示例;- const zip = new JSZip();
-
- // 添加一个文件到 ZIP 中
- zip.file("hello.txt", "Hello world!");
-
- // 生成ZIP压缩文件的异步操作
- zip.generateAsync({ type: "blob" })
- .then((content) => {
- // Do something
- });
FileSaver 则用于将数据保存为文件。主要使用saveAs()方法,接受两个参数:要保存的文件名和要保存的数据。使用方法如下:[data]为二进制数据,将被保存到新创建image.jpg的本地文件中
- const blob = new Blob( [data], {type : 'image/jpeg'} );
- FileSaver.saveAs( blob, 'image.jpg' );
在页面中引入上述库
- import JSZip from 'jszip'
- import FileSaver from 'file-saver'
图片的展示和保存都需要提前获取图片,先完成单个图片请求。此处,需使用responseType: 'blob'
,因为图片是二进制数据,而不是文本数据。如果我们将responseType设置为'text',则浏览器会尝试将二进制数据解析为文本数据,这将导致数据损坏。通过将responseType设置为'blob',我们告诉浏览器将响应数据作为二进制对象处理,这样我们就可以正确地下载图片。
图片的签名信息获取,需要通过另外的接口get到,后续处理。此外,请求涉及到了跨域问题,通过Nginx代理解决,属于后端内容不再赘述。
- // 单个图片下载
- getFile(item) {
- return new Promise((resolve, reject) => {
- this.axios({
- url: baseUrl + item.requestUrl,
- method: 'get',
- headers: {
- 'Authorization': item.authToken,
- 'Signature': item.reqSignature,
- 'ClientId': item.clientId
- },
- // 设置此选项,响应数据类型设置为blob(arraybuffer也OK);未设置时请求数据为乱码
- responseType: 'blob'
- }).then((response) => {
- resolve(response) // 将下载的文件返回
- }).catch((error) => {
- reject(error.toString())
- })
- })
- },
请求方法完成后,点击页面按钮触发showImage展示图片,此方法中调用getFile()获取图片,并显示在el-dialog弹窗中。实现中需要注意getFile()方法响应的数据是Blob对象,需要将其转换为url,以便赋值给el-image的src属性。
- showImage(item) {
- this.startLoading()
- getImageTokenById({ idFaultResource: parseInt(item.value) }).then((resp) => {
- console.log(JSON.stringify(resp))
- if (resp.code === '200') {
- const param = {
- // resourceKey: resp.result.resourceKey,
- requestUrl: resp.result.requestUrl,
- authToken: resp.result.authToken,
- reqSignature: resp.result.reqSignature,
- clientId: resp.result.clientId
- }
- this.getFile(param).then((response) => {
- this.endLoading()
- this.dialogVisible = true
- console.log(JSON.stringify(response))
- // urlCreator用于创建URL对象。在浏览器中,window.URL和window.webkitURL对象可能存在一个或两个
- const urlCreator = window.URL || window.webkitURL
- // createObjectURL方法将一个Blob或MediaStream对象转换为URL,以便赋值给el-image的src属性
- const imageUrl = urlCreator.createObjectURL(response.data)
- console.log('URL::::' + JSON.stringify(imageUrl))
- this.dialogImageUrl = imageUrl
- this.dialogImageName = resp.result.resourceKey
- this.imageBlob = [response.data]
- }).catch((error) => {
- this.$message({
- showClose: true,
- message: '获取图片失败,' + error,
- type: 'error'
- })
- this.endLoading()
- })
- }
- }).catch((error) => {
- this.$message({
- showClose: true,
- message: error,
- type: 'error'
- })
- this.endLoading()
- })
- },
注:getImageById()方法需要提前获取签名信息;
图片展示弹窗十分简单,添加标题,图片关闭按钮和下载按钮即可
- <el-dialog
- title="图片预览"
- :visible.sync="dialogVisible"
- size="tiny"
- :before-close="handleClose"
- >
- <!-- 图片展示 -->
- <el-image :src="dialogImageUrl" alt="图片加载中……" style="width: 100%;height: 100%;" />
- <span slot="footer" class="dialog-footer">
- <el-button type="primary" @click="saveImage(imageBlob, dialogImageName)">下载图片</el-button>
- </span>
- </el-dialog>
点击下载图片调用saveAs()方法保存图片,将图片文件按照imageName命名保存,并隐藏弹窗。
- saveImage(data, imageName) {
- const blob = new Blob(data, { type: 'image/jpeg' })
- FileSaver.saveAs(blob, imageName + '.jpg')
- this.dialogImageUrl = ''
- this.dialogVisible = false
- this.$message({
- showClose: true,
- message: '图片下载完成!',
- type: 'success'
- })
- },
批量下载只需要,将图片列表遍历逐个下载,待所有图片下载完成调用saveAs()方法保存并压缩生成文件夹。
- // 批量导出图片
- downloadFile() {
- const zip = new JSZip()
- const imagesPromises = []
- const cache = {}
- this.startLoading()
- getImagesTokenById ({ idTrustOrder: this.idTrustOrder }).then((resp) => {
- if (resp.code === '200') {
- const imageList = resp.result.downloadImageList
- if (imageList.length === 0) {
- this.$message({
- showClose: true,
- message: '当前无可下载的故障内容!',
- type: 'warning'
- })
- this.endLoading()
- return
- }
- imageList.map((item) => {
- const promise = this.getFile(item).then((resp) => {
- // 逐个下载图片
- console.log('获取的图片内容::' + item.resourceKey + '.jpg' + resp.data)
- // 创建文件用file()方法,文件夹用floder()方法
- zip.file(item.resourceKey + '.jpg', resp.data, { binary: true })
- cache[item.resourceKey] = resp.data
- })
- imagesPromises.push(promise)
- })
- // 生成zip文件
- Promise.all(imagesPromises)
- .then(() => {
- this.endLoading()
- zip.generateAsync({
- type: 'blob' // 文件格式
- }).then((content) => {
- // 生成二进制流
- FileSaver.saveAs(content, '图片.zip') // 利用file-saver保存文件,自定义文件名图片.zip
- this.$message({
- showClose: true,
- message: '文件下载完成!',
- type: 'success'
- })
- })
- })
- .catch((error) => {
- this.$message({
- showClose: true,
- message: '文件下载失败!' + error,
- type: 'error'
- })
- this.endLoading()
- })
- }
- }).catch((error) => {
- this.$message({
- showClose: true,
- message: error,
- type: 'error'
- })
- this.endLoading()
- })
- },
测试功能可用,开发中遇到的问题主要是跨域,二进制数据的处理,还有IT限制我的接口
参考文献:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。