uniapp项目实践总结(十三)封装文件操作方法

导语:在日常 APP 开发过程中,经常要进行文件的保存、读取列表以及查看和删除文件等操作,接下来就看一下具体的方法。

目录

  • 原理分析
  • 方法实现
  • 实战演练
  • 案例展示

原理分析

主要是以下 API。

  • uni.saveFile:保存文件到本地缓存列表;
  • uni.getSavedFileList:获取保存文件列表;
  • uni.getSavedFileInfo:获取文件详细信息;
  • uni.removeSavedFile:移除保存的文件;
  • uni.openDocument:打开文档;

以下方法存于根目录下的scripts文件夹下的http.js文件中。

方法实现

接下来一一说明如何实现数据请求、文件下载以及文件的上传的方法封装。

保存文件

保存文件这里使用条件编译,分别对 h5、微信小程序、APP 进行了对应方法的封装。

  • 总体方法

这里主要是进行参数的处理,包括默认参数,传入参数,合并参数。

js 复制代码
// 保存图片
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 保存文件

这个主要是使用fetchAPI 进行文件下载,然后使用a标签进行点击下载。

js 复制代码
// #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.getFileSystemManagerAPI 来获取文件管理器接口,然后进行下载保存文件。

js 复制代码
// #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方法保存文件。

js 复制代码
// #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 是封装的一个方法,用于获取特定终端下面的文件管理方法。

js 复制代码
// 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;
}

文件列表

这个支持传入文件路径,获取特定文件信息。

js 复制代码
// 保存文件列表
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,
    };
  }
}

查看文件

js 复制代码
// 打开文件
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,
    };
  }
}

删除文件

js 复制代码
// 删除文件
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,
    };
  }
}

写好以后记得导出方法。

实战演练

模板内容

  • 保存文件
html 复制代码
<button type="primary" size="mini" @click="saveFile('file')" v-if="httpInfo.uploadFileUrl">
  保存文件
</button>
  • 文件列表
html 复制代码
<!-- #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 -->

脚本方法

  • 定义数据
js 复制代码
let httpInfo = reactive({
  fileList: [],
});
  • 保存文件
js 复制代码
// 保存文件
function saveFile(type = "img") {
  let url = httpInfo[type == "img" ? "uploadImgUrl" : "uploadFileUrl"];
  if (url) {
    console.log("要保存的文件:", url);
    proxy.$http.saveFile({
      url,
      name: httpInfo.fileName,
    });
  }
}
  • 文件列表
js 复制代码
// #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
  • 查看文件
js 复制代码
// #ifdef APP-PLUS
// 查看文件
async function openFile(item) {
  let data = await proxy.$http.openFile(item.filePath);
  console.log("查看文件结果:", data);
}

// #endif
  • 删除文件
js 复制代码
// #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

案例展示

  • 保存文件
  • 查看文件
  • 删除文件

最后

以上就是封装文件操作方法的主要内容,有不足之处,请多多指正。

相关推荐
海晨忆27 分钟前
【Vue】v-if和v-show的区别
前端·javascript·vue.js·v-show·v-if
JiangJiang1 小时前
🚀 Vue人看React useRef:它不只是替代 ref
javascript·react.js·面试
1024小神1 小时前
在GitHub action中使用添加项目中配置文件的值为环境变量
前端·javascript
龙骑utr1 小时前
qiankun微应用动态设置静态资源访问路径
javascript
Jasmin Tin Wei1 小时前
css易混淆的知识点
开发语言·javascript·ecmascript
齐尹秦1 小时前
CSS 列表样式学习笔记
前端
wsz77771 小时前
js封装系列(一)
javascript
Mnxj1 小时前
渐变边框设计
前端
用户7678797737321 小时前
由Umi升级到Next方案
前端·next.js
快乐的小前端1 小时前
TypeScript基础一
前端