#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
方法的调用过程,我们可以绘制一个更详细的流程图,展示这个方法内部的逻辑分支和调用顺序。以下是根据您提供的代码绘制的流程图:
流程图解释:
- 开始:流程的起点。
- 调用 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
方法在不同平台环境下的执行逻辑和分支。