不太会使用编辑器 我就贴些图和代码吧
这些是我经过最近一段时间查阅资料研究,得出的相对比较齐全uniapp app端文件下载方式
方式一
利用H5+的方法plus.downloader.createDownload,支持更改文件名,但只支持oss等网络文件,不支持文件流,支持app里的webview页面调用。
调用方式:downLoadFileAndSave('xxxxx.xls', 'lwq.xls')
// 创建文件夹,path值为:"/storage/emulated/0/自定义文件夹名称"
export const createDir = async(path) => {
return new Promise((resolve, reject) => {
// 申请本地存储读写权限
plus.android.requestPermissions([
'android.permission.WRITE_EXTERNAL_STORAGE',
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.INTERNET',
'android.permission.ACCESS_WIFI_STATE'
], success => {
const File = plus.android.importClass('java.io.File')
const file = new File(path)
// 文件夹不存在即创建
if (!file.exists()) {
file.mkdirs()
}
resolve()
}, error => {
uni.$u.toast('无法获取权限,文件下载将出错')
reject(error)
})
})
}
/**
* {url} 下载地址
* {name} 保存文件时 重命名
* {cb1,cb2} 下载进度和完成 的回调
* :下载大文件“可能”会内存溢出
* */
// downLoadFileAndSave('http://xxxxx.xls', 'lwq.xls')
export const downLoadFileAndSave = async(url, name, cb1, cb2) => {
let progressVal = 0
const osName = plus.os.name
const path = '/storage/emulated/0/Download/Mro'
try {
if (osName === 'Android') {
await createDir(path)
}
const selfName = url.split('/').pop() // 获取文件名
if (!name) {
name = selfName
}
const filename = osName === 'Android' ? 'file://' + path + '/' + name : '_downloads/' + name
var dtask = plus.downloader.createDownload(url, {
// filename: '_downloads/' + name // 利用保存路径,实现下载文件的重命名
// filename: 'file://' + path + '/' + name // 利用保存路径,实现下载文件的重命名
filename
}, function(d, status) {
// d为下载的文件对象
if (status == 200) {
console.log(osName + '下载成功', d)
if (cb2) {
cb2(d)
return
}
// 下载成功,d.filename是文件在保存在本地的相对路径,使用下面的API可转为平台绝对路径
// var fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename)
// plus.runtime.openFile(d.filename) // 选择软件打开文件
if (osName === 'Android') {
uni.showToast({
title: '文件已保存',
icon: 'success'
})
} else {
uni.showModal({
title: '提示',
content: '如需保存到本地,需要打开文件点击储存',
// cancelText: '我知道了',
confirmText: '打开文件',
success: function(res) {
if (res.confirm) {
uni.openDocument({
filePath: d.filename,
success: (sus) => {
// console.log('成功打开')
}
})
}
}
})
}
} else {
// 下载失败
console.log('下载失败', d)
plus.downloader.clear() // 清除下载任务
}
})
dtask.addEventListener('statechanged', (task) => {
if (!dtask) {
return
}
switch (task.state) {
case 1:
console.log('开始下载')
break
case 2:
console.log('链接到服务器...')
break
case 3:
progressVal = (changeTwoDecimal_f(task.downloadedSize / task.totalSize) * 100) + '%'
if (cb1) cb1(progressVal)
break
case 4:
console.log('监听下载完成')
break
}
})
dtask.start()
} catch (error) {
console.log(error)
}
}
/**
* 例如
* 2 → 2.00
* 2.3 → 2.30
* 2.321 → 2.32
* 2.328 → 2.33
*
* */
function changeTwoDecimal_f(x) {
var f_x = parseFloat(x)
if (isNaN(f_x)) {
return 0
}
var f_x = Math.round(x * 100) / 100
var s_x = f_x.toString()
var pos_decimal = s_x.indexOf('.')
if (pos_decimal < 0) {
pos_decimal = s_x.length
s_x += '.'
}
while (s_x.length <= pos_decimal + 2) {
s_x += '0'
}
return s_x
}
效果图: 安卓的保存:
IOS的保存:
方式二:
特点:利用uni.downloadFile方法(只能是GET请求)+plus.io.convertLocalFileSystemURL等方法,通过uni.openDocument预览PDF、Excel、Word等文件,支持文件流、OSS文件下载 支持更改文件名,支持app里的webview页面调用。
调用方式:downLoadFileAndSave('xxxxx.xls', 'lwq.xls')
调用方式:downLoadFileAndSave('http://文件流的接口', 'lwq.xls')
handleDownload(url, name) {
const that = this
uni.downloadFile({ // 只能是GET请求
url,
header: {
'Authorization': uni.getStorageSync('token')
},
success: (res) => {
// 下载成功
if (res.statusCode === 200) {
// 拿到临时文件的绝对路径
const filepathss = plus.io.convertLocalFileSystemURL(res.tempFilePath)
// 通过这个路径来拿到他
plus.io.resolveLocalFileSystemURL(filepathss, function(entry) {
const tempFileName = entry.name
entry.getParent(function(parentDicEntry) {
entry.moveTo({ fullPath: parentDicEntry.fullPath + '/' }, name, function(newFile) {
that.handleOpen(newFile.fullPath)
}, function(moveError) {
// uni.showToast({
// title: `已在第三方应用中打开过,请在第三方应用查看时保存`,
// icon: 'none'
// })
that.handleOpen(parentDicEntry.fullPath + '/' + name)
})
})
})
}
},
fail: (e) => {
this.isDownloading = false
uni.showToast({
title: `文件下载失败`,
icon: 'none'
})
}
})
},
handleOpen(filePath) {
uni.showModal({
title: '提示',
content: '如需保存到本地,需要打开文件再保存',
// cancelText: '我知道了',
confirmText: '打开文件',
success: function(res) {
if (res.confirm) {
// 保存成功之后 打开文件
uni.openDocument({
filePath,
fail: (e) => {
uni.showToast({
title: `打开失败,可先安装office软件(WPS)再尝试打开`,
icon: 'none',
duration: 2000
})
}
})
}
}
})
},
方式三:
特点:利用uni.request arraybuffer,plus.io里的writer.writeAsBinary(base64)方法,通过uni.openDocument预览PDF、Excel、Word等文件,支持文件流、OSS文件下载 支持更改文件名,支持app里的webview页面调用。
writer.writeAsBinary(base64) 这个方法非常重要,对后续的大文件分片下载非常有帮助。
调用方式:如下
uni.request({
url: '文件流接口 或 http:/xxxx.xls', // 支持文件流、OSS文件下载
method: 'GET',
responseType: 'arraybuffer',
header: {
'Authorization': 'Bxxx'
},
success: (res) => {
const base64 = uni.arrayBufferToBase64(res.data)
const filePath = '_documents/xxxx.xls' // 自定义路径
// 写入文件
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {
fs.root.getFile(filePath, { create: true }, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwrite = function(e) {
plus.nativeUI.alert('文件已保存', function() {
plus.runtime.openFile(filePath) // 打开文件
})
}
writer.onerror = function(e) {
console.error('写入失败: ' + e.message)
}
// writer.write(res.data)
writer.writeAsBinary(base64)
}, function(e) {
console.error('创建Writer失败: ' + e.message)
})
}, function(e) {
console.error('获取文件失败: ' + e.message)
})
}, function(e) {
console.error('请求文件系统失败: ' + e.message)
})
}
})
方式四:大文件分片下载
上面3种下载方式是我经过最近一段时间查阅资料苦逼研究出来的,其中方式三更是如此,得出的相对比较齐全uniapp app端文件下载方式。
至于方式四大文件分片下载,全网没找到实现方法,几经波折自己硬啃下来,但文件较大时写入问题有问题,最终还是得采取跳转浏览器打开页面下载的方式。