导语:在日常 APP 开发过程中,经常要进行文件的保存、读取列表以及查看和删除文件等操作,接下来就看一下具体的方法。
目录
- 原理分析
- 方法实现
- 实战演练
- 案例展示
原理分析
主要是以下 API。
uni.saveFile
:保存文件到本地缓存列表;uni.getSavedFileList
:获取保存文件列表;uni.getSavedFileInfo
:获取文件详细信息;uni.removeSavedFile
:移除保存的文件;uni.openDocument
:打开文档;
以下方法存于根目录下的scripts
文件夹下的http.js
文件中。
方法实现
接下来一一说明如何实现数据请求、文件下载以及文件的上传的方法封装。
保存文件
保存文件这里使用条件编译,分别对 h5、微信小程序、APP 进行了对应方法的封装。
- 总体方法
这里主要是进行参数的处理,包括默认参数,传入参数,合并参数。
// 保存图片
async function saveFile(options) {
let isHttp = options.url.indexOf("http") > -1;
let url = isHttp ? options.url : `${urls.baseUrl}${options.url}`;
let defultOptions = {
url,
name: options.name || utils.uuid(),
extName: options.extName || utils.fileExt(url),
filePath: options.filePath,
};
let params = { ...options, ...defultOptions };
console.log("保存文件参数:", params);
// h5代码
// 微信小程序代码
// APP 代码
}
- h5 保存文件
这个主要是使用fetch
API 进行文件下载,然后使用a
标签进行点击下载。
// #ifdef H5
fetch(url, {
mode: "cors",
})
.then(async (res) => {
const e = await res.blob();
return e;
})
.then((blob) => {
const fileElem = document.createElement("a");
let fileUrl = URL.createObjectURL(blob);
fileElem.style.display = "none";
fileElem.href = fileUrl;
fileElem.download = `${params.name}.${params.extName}`;
document.body.appendChild(fileElem);
fileElem.click();
setTimeout(() => {
URL.revokeObjectURL(fileUrl);
fileElem.remove();
}, 1000);
});
// #endif
- 微信小程序保存文件
这个主要是使用微信小程序的wx.getFileSystemManager
API 来获取文件管理器接口,然后进行下载保存文件。
// #ifdef MP-WEIXIN
const fs = wx.getFileSystemManager(),
userDataPath = wx.env.USER_DATA_PATH;
const filePath = params.filePath || `${userDataPath}/${params.name}.${params.extName}`;
wx.showLoading({
title: "文件下载中...",
});
wx.downloadFile({
url,
success(res) {
let tempFile = res.tempFilePath;
let img = ["png", "jpg", "gif"];
if (tempFile && img.includes(params.extName)) {
wx.saveImageToPhotosAlbum({
filePath: tempFile,
success: function () {
wx.showToast({
title: "保存成功!",
icon: "success",
});
},
fail() {
wx.showToast({
title: "保存失败!",
icon: "error",
});
},
});
} else {
fs.saveFile({
tempFilePath: tempFile,
filePath,
success: function () {
wx.showToast({
title: "保存成功!",
icon: "success",
});
},
fail() {
wx.showToast({
title: "保存失败!",
icon: "error",
});
},
});
}
},
fail() {
wx.showToast({
title: "下载失败!",
icon: "error",
});
},
complete() {
wx.hideLoading();
},
});
// #endif
- APP 保存文件
这里主要是使用uni.saveFile
方法保存文件。
// #ifdef APP-PLUS
uni.showLoading({
title: "文件下载中...",
});
let opts = {
url,
};
let data = await download(opts);
if (data) {
uni.saveFile({
tempFilePath: data,
success: function (res) {
uni.showToast({
title: "保存成功!",
icon: "success",
});
},
fail() {
uni.showToast({
title: "保存失败!",
icon: "error",
});
},
complete() {
uni.hideLoading();
},
});
} else {
uni.showToast({
title: "下载失败!",
icon: "error",
});
}
// #endif
获取文件管理
下面的 getIfs
是封装的一个方法,用于获取特定终端下面的文件管理方法。
// utils.js
// 文件操作
function getIfs() {
let ifs = {
list: null,
info: null,
delete: null,
open: null,
};
// #ifdef MP-WEIXIN
let fsm = wx.getFileSystemManager();
ifs.list = fsm.getSavedFileList;
ifs.info = fsm.getFileInfo;
ifs.delete = fsm.unlink;
ifs.open = fsm.open;
// #endif
// #ifdef APP-PLUS
ifs.list = uni.getSavedFileList;
ifs.info = uni.getSavedFileInfo;
ifs.delete = uni.removeSavedFile;
ifs.open = uni.openDocument;
// #endif
return ifs;
}
文件列表
这个支持传入文件路径,获取特定文件信息。
// 保存文件列表
async function fileList(filePath) {
try {
let ifs = utils.getIfs(),
list = [];
let data = await ifs.list();
if (data.fileList) {
list = data.fileList;
if (list.length) {
for (let item of list) {
item.name = utils.fileName(item.filePath);
item.id = utils.uuid();
item.sizeText = utils.fileSize(item.size);
item.timeText = utils.nowDate(item.createTime).normal;
}
}
if (filePath) {
list = list.filter((s) => filePath === s.filePath);
}
return {
code: 1,
data: list,
};
} else {
return {
code: 2,
data: data.errMsg,
};
}
} catch (e) {
//TODO handle the exception
return {
code: 2,
data: e,
};
}
}
查看文件
// 打开文件
async function openFile(filePath = "", showMenu = true) {
try {
if (!filePath) {
return {
code: 2,
data: "文件路径不能为空!",
};
}
let ifs = utils.getIfs();
let result = await ifs.open({
filePath,
showMenu,
});
if (result) {
return {
code: 1,
data: "打开成功!",
};
} else {
return {
code: 2,
data: "打开失败!",
};
}
} catch (e) {
//TODO handle the exception
return {
code: 2,
data: e,
};
}
}
删除文件
// 删除文件
async function deleteFile(filePath) {
try {
if (!filePath) {
return {
code: 2,
data: "文件路径不能为空!",
};
}
let ifs = utils.getIfs();
let result = await ifs.delete({
filePath,
});
if (result) {
return {
code: 1,
data: "删除成功!",
};
} else {
return {
code: 2,
data: "删除失败!",
};
}
} catch (e) {
//TODO handle the exception
return {
code: 2,
data: e,
};
}
}
写好以后记得导出方法。
实战演练
模板内容
- 保存文件
<button type="primary" size="mini" @click="saveFile('file')" v-if="httpInfo.uploadFileUrl">
保存文件
</button>
- 文件列表
<!-- #ifdef APP-PLUS -->
<view class="list-http">
<button @click="getFileList">文件列表</button>
<text class="list-http-txt">响应内容:</text>
<view class="list-file" v-for="(item, index) in httpInfo.fileList" :key="item.id">
<view class="list-file-item">文件名称:{{ item.name }}</view>
<view class="list-file-item">文件大小:{{ item.sizeText }}</view>
<view class="list-file-item">文件路径:{{ item.filePath }}</view>
<view class="list-file-item">保存时间:{{ item.timeText }}</view>
<view class="list-file-item">
<button size="mini" type="primary" @click="openFile(item)">查看文件</button>
<button size="mini" type="warn" @click="delFile(item, index)">删除文件</button>
</view>
</view>
</view>
<!-- #endif -->
脚本方法
- 定义数据
let httpInfo = reactive({
fileList: [],
});
- 保存文件
// 保存文件
function saveFile(type = "img") {
let url = httpInfo[type == "img" ? "uploadImgUrl" : "uploadFileUrl"];
if (url) {
console.log("要保存的文件:", url);
proxy.$http.saveFile({
url,
name: httpInfo.fileName,
});
}
}
- 文件列表
// #ifdef APP-PLUS
// 获取文件列表
async function getFileList() {
let filePath = "_doc/uniapp_save/16928451309592.srt";
let data = await proxy.$http.fileList();
if (data.code == 1) {
httpInfo.fileList = data.data;
}
}
// #endif
- 查看文件
// #ifdef APP-PLUS
// 查看文件
async function openFile(item) {
let data = await proxy.$http.openFile(item.filePath);
console.log("查看文件结果:", data);
}
// #endif
- 删除文件
// #ifdef APP-PLUS
// 删除文件
async function delFile(item, index) {
let data = await proxy.$http.deleteFile(item.filePath);
if (data.code === 1) {
httpInfo.fileList.splice(index, 1);
uni.showToast({
title: data.data,
icon: "success",
});
} else {
uni.showToast({
title: data.data,
icon: "error",
});
}
}
// #endif
案例展示
-
保存文件
-
查看文件
-
删除文件
最后
以上就是封装文件操作方法的主要内容,有不足之处,请多多指正。