#Uniapp# #HTML 5+#
当前方案支持的平台如下:
- H5
- 微信小程序
- APP
- Android
- IOS
代码方案
<ss-download ref="ssdownload" :suffix="suffix"/>
// 下载控件ref对象
const ssdownload = ref(null)
// 文件类型枚举
const fileTypeEnum = { img: 1, file: 2, video: 3,
}
// 文件类型
const fileType = (fileUrl) => { // 文件后缀 const suffix = fileUrl.split('.').pop() // 文件类型 if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(suffix)) { return fileTypeEnum.img } else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'txt', 'psd'].includes(suffix)) { return fileTypeEnum.file } else if (['mp4', 'avi', 'rmvb', 'rm', 'flv', 'mov', '3gp', 'wmv', 'mkv'].includes(suffix)) { return fileTypeEnum.video } else { return fileTypeEnum.file }
}
// 处理文件下载方法
const handleDownload = (url) => { if (!url) { uni.showToast({title: '文件已失效,当前无法下载', icon: 'none'}) return } const item = { src: url, type: fileType(url) } ssdownload.value.toDownload(item)
}
ss-download.vue
<template> <view></view></template> <script>
export default { name: 'ss-download', props: { suffix: { type: String, default: '' }, fileUrl: { type: String, default: '' }, fileType: { type: String, default: '', }, }, data() { return {}; }, methods: { toDownload(item) { console.log('item', item) // #ifdef H5 this.downloadH5(item.src) // #endif // #ifdef MP-WEIXIN if (item.type === 1) { this.saveToPhotosAlbum(item.src) } else if (item.type === 2) { this.saveFile(item.src) } else { this.getDownVideo(item.src) } // #endif // #ifdef APP-PLUS this.saveFileToApp(item.src) // #endif }, //H5下载图片到本地 downloadH5(url) { uni.downloadFile({ url: url, success: (res) => { console.log(res) if (res.statusCode === 200) { console.log('下载成功'); let oA = document.createElement("a"); oA.download = ''; // 设置下载的文件名,默认是'下载' oA.href = res.tempFilePath; //临时路径再保存到本地 document.body.appendChild(oA); oA.click(); oA.remove(); // 下载之后把创建的元素删除 } }, fail(err) { console.log(err) } }); }, //微信小程序保存文档,不支持h5 saveFile(url) { const fileName = new Date().valueOf(); uni.showLoading({ title: '下载中...' }) uni.downloadFile({ //下载文件资源到本地,返回文件的本地临时路径 url: url, //网络图片路径 success: (res) => { console.log(res) uni.showModal({ title: '提示', content: '保存成功,请选择聊天转发分享后查看', showCancel: false, icon: 'success', }) uni.shareFileMessage({ filePath: res.tempFilePath, fileName: fileName + '.' + url.split('.').pop(), success: function (res) { console.log('success') console.log(res) uni.hideLoading() }, fail: function (err) { console.log('fail') console.log(err) uni.hideLoading() uni.showToast({ title: '下载失败', icon: 'none', }) }, complete: function (res) { console.log('complete') console.log(res) } }) }, fail(err) { uni.hideLoading() uni.showToast({ title: '下载失败', icon: 'none', }) } }) }, //微信小程序保存视频 getDownVideo(url) { // 自定义 文件名称 uni.showLoading({ mask: true, title: '下载中...' }) let fileName = new Date().valueOf(); const task = uni.downloadFile({ url: url, filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.' + this.data.suffix, // 拼接本地文件路径 success: (res) => { let filePath = res.filePath uni.saveVideoToPhotosAlbum({ filePath, success: (res) => { uni.showToast({ title: '下载成功', icon: 'success', }) let fileMgr = wx.getFileSystemManager(); // 删除本地文件 fileMgr.unlink({ filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.' + this.data.suffix, success: function (r) { console.log('unlink-getFileSystemManager') console.log(r) }, }) }, fail(err) { uni.showToast({ title: '保存失败', icon: 'none', }) }, complete(res) { console.log('saveVideoToPhotosAlbum-complete') console.log(res) uni.hideLoading() } }) }, fail(err) { uni.showToast({ title: '下载失败,请稍后再试', icon: 'none', }) }, complete(res) { console.log(res) } }) task.onProgressUpdate(this.onProgress) }, // 提示下载进度 onProgress(res) { uni.showLoading({ mask: true, title: res.progress ? '下载中' + res.progress + "%" : '下载中...' }) }, //微信小程序保存图片(此处也可用于app保存图片或视频) saveToPhotosAlbum(url) { // #ifdef APP-PLUS const showLoading = plus.nativeUI.showWaiting("正在下载"); //创建一个showWaiting对象 // #endif let task = uni.downloadFile({ url: url, success: res => { const { statusCode, tempFilePath } = res if (statusCode === 200) { // saveImageToPhotosAlbum saveVideoToPhotosAlbum uni.saveImageToPhotosAlbum({ //此处也可用saveVideoToPhotosAlbum filePath: tempFilePath, success: data => { uni.showToast({ title: '下载成功,文件已保存到相册', icon: 'success', }) }, complete: (msg) => { // #ifdef APP-PLUS plus.nativeUI.closeWaiting() // #endif } }); } else { uni.showToast({ title: '下载失败', icon: 'none', }) // #ifdef APP-PLUS plus.nativeUI.closeWaiting() // #endif } }, complete: () => { } }) task.onProgressUpdate((res => { // console.log('上传进度' + res.progress); // console.log('已经上传的数据长度' + res.totalBytesSent); // console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend); showLoading.setTitle(" 正在下载" + res.progress + "% "); })) }, //移动端下载文件 saveFileToApp(url) { let fileName = new Date().valueOf() + '.' + url.split('.').pop(); console.log('【文件下载】文件路径:' + url); console.log('【文件下载】文件名:' + fileName); const downloadTask = plus.downloader.createDownload(url, { filename: "_downloads/" + fileName }, function (d, status) { uni.showToast({ title: '【文件下载】下载完成', mask: false, duration: 1000 }); // 下载完成 console.log('status: ' + status); if (status === 200) { let filePath = d.filename plus.io.getFileInfo({ filePath, digestAlgorithm: 'md5', success: function (info) { console.log('【文件下载】文件大小:' + info.size); }, fail: function (err) { console.log('【文件下载】获取文件信息失败:' + JSON.stringify(err)); }, complete: function (res) { console.log('【文件下载】获取文件信息完成:' + JSON.stringify(res)); } }); // console.log('【文件下载】下载文件成功:' + url); // filePath = plus.io.convertLocalFileSystemURL(url); console.log('【文件下载】本地文件路径: ' + filePath); plus.runtime.openFile(filePath, {}, (err) => { console.log('【文件下载】打开文件失败:', err) }) } else { uni.showToast({ title: '【文件下载】下载失败', mask: false, duration: 1500 }); } }); try { downloadTask.start(); // 开启下载的任务 let prg = 0; const showLoading = plus.nativeUI.showWaiting("正在下载"); //创建一个showWaiting对象 downloadTask.addEventListener('statechanged', function (task, status) { // 给下载任务设置一个监听 并根据状态 做操作 switch (task.state) { case 1: showLoading.setTitle("正在下载"); break; case 2: showLoading.setTitle("已连接到服务器"); break; case 3: prg = parseInt((parseFloat(task.downloadedSize) / parseFloat(task.totalSize)) * 100); showLoading.setTitle(" 正在下载" + prg + "% "); break; case 4: plus.nativeUI.closeWaiting(); //下载完成 break; } }); } catch (err) { plus.nativeUI.closeWaiting(); uni.showToast({ title: '更新失败', mask: false, duration: 1500 }); } }, },
};
</script>
关于toDownload
方法的调用过程,我们可以绘制一个更详细的流程图,展示这个方法内部的逻辑分支和调用顺序。以下是根据您提供的代码绘制的流程图:
graph TDA[开始] --> B[调用 toDownload 方法]B --> C{判断平台}C -->|H5平台| D[下载H5文件]C -->|微信小程序| E{判断item.type}C -->|APP-PLUS平台| F[下载文件到APP]E -->|item.type === 1| G[保存到相册]E -->|item.type === 2| H[保存文件]E -->|其他| I[下载视频]D --> J[下载H5文件流程结束]G --> K[保存图片到相册流程结束]H --> L[保存文件流程结束]I --> M[下载视频流程结束]F --> N[下载文件到APP流程结束]J --> O[流程结束]K --> OL --> OM --> ON --> O
流程图解释:
- 开始:流程的起点。
- 调用 toDownload 方法:开始执行
toDownload
方法。 - 判断平台:根据代码中的编译指令(
#ifdef
),判断当前运行的平台环境。 - 下载H5文件:如果是H5平台,执行H5文件下载逻辑。
- 判断item.type:如果是微信小程序平台,根据
item.type
的值来决定执行哪个具体的下载或保存操作。 - 保存到相册:当
item.type === 1
时,执行保存图片到相册的操作。 - 保存文件:当
item.type === 2
时,执行保存文件的操作。 - 下载视频:其他情况,执行下载视频的操作。
- 下载文件到APP:如果是APP-PLUS平台,执行下载文件到APP的操作。
- 下载H5文件流程结束:H5文件下载流程结束。
- 保存图片到相册流程结束:保存图片到相册流程结束。
- 保存文件流程结束:保存文件流程结束。
- 下载视频流程结束:下载视频流程结束。
- 下载文件到APP流程结束:下载文件到APP流程结束。
- 流程结束:整个
toDownload
方法的执行流程结束。
这个流程图清晰地展示了toDownload
方法在不同平台环境下的执行逻辑和分支。