首页 > 其他分享 >uniapp项目实践总结(十三)封装文件操作方法

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

时间:2023-09-08 20:55:39浏览次数:44  
标签:uniapp 封装 文件 操作方法 filePath let uni data ifs

导语:在日常 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 保存文件

这个主要是使用fetchAPI 进行文件下载,然后使用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.getFileSystemManagerAPI 来获取文件管理器接口,然后进行下载保存文件。

// #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

案例展示

  • 保存文件
    image

  • 查看文件
    image

  • 删除文件
    image

最后

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

标签:uniapp,封装,文件,操作方法,filePath,let,uni,data,ifs
From: https://www.cnblogs.com/guanqiweb/p/17688533.html

相关文章

  • 【设计模式】命令模式Command:在一次请求中封装多个参数
    (目录)命令模式使用频率不算太高。如果熟悉函数式编程的话,会发现命令模式完全没有使用的必要,甚至在业务开发的场景中也很少使用到。不过对于想要找到正确抽象的设计者来说,命令模式的设计思想却非常值得借鉴。命令和查询的区别:查询,获取一个不可变的结果;命令,改变状态,不一定获......
  • Java泛型对象在http请求和响应对象中的封装
    Java泛型对象在http请求和响应对象中的封装publicclassMySystemBaseResVo<T>{//注意:类的后面需要带上<T>,否则数据无法封装privateStringerr_no;privateStringerr_tips;privateTdata;publicStringgetErr_no(){returnerr_no;}......
  • React项目笔记-环境搭建、路由封装(跳转Navigate、懒加载lazy)、模块化样式引入、状态管
    环境准备nodev16.15.0npm8.5.5AntDesignofReact:https://ant.design/docs/react/introduce-cn一,创建项目npminitvite√Projectname:...vite-project-react√Selectaframework:»React√Selectavariant:»TypeScript然后使用vscode打开项目,由于......
  • 封装
    封装-提高程序安全性,保护数据-隐藏代码的实现细节-统一接口-系统可维护性增加publicclassAPPlication{publicstaticvoidmain(String[]args){Students1=newStudent();s1.setName("Duncan");System.out.println(s1.g......
  • uniapp项目实践总结(十二)封装通用请求上传以及下载方法
    导语:在日常开发过程中,前端经常要和后端进行接口联调,获取并且渲染数据到页面中,接下来就总结一下uniapp中获取请求、文件下载和上传的一些方法。目录原理分析方法实现实战演练案例展示原理分析主要是使用uni.request方法来发送请求,uni.downloadFile方法来下载文件,uni.u......
  • Vue中数组操作方法有哪些?
    在Vue中,有一些数组操作方法是专门为了处理响应式数组而提供的。这些方法会触发Vue的响应式更新机制,确保视图能够正确地响应数组的变化。以下是Vue提供的数组操作方法:1:push():向数组末尾添加一个或多个元素,并返回新的长度。this.array.push('newitem');2:pop():移除数组的最后一......
  • Vue的数组操作方法和JavaScript原生数组方法有什么区别?
    Vue的数组操作方法和JavaScript原生数组方法之间存在一些区别,主要体现在对响应式更新的处理上。#####1:响应式更新:Vue数组操作方法是对JavaScript原生数组方法的封装,能够触发Vue的响应式更新机制。这意味着当你使用Vue的数组操作方法修改数组时,Vue会自动检测到数组的变化......
  • Uniapp生命周期
    Uniapp页面&组件生命周期页面的生命周期uni-app支持如下生命周期函数:onLoad监听页面加载,其参数为上个页面传递的数据,参数类型为object(用于页面传参)onShow监听页面显示onReady监听页面初次渲染完成onHide监听页面隐藏onUnload监听页面卸载onPullDownRefresh监听用......
  • uniApp 再下一页修改上一页的值
    letpages=getCurrentPages();//获取所有页面栈实例列表 letnowPage=pages[pages.length-1];//当前页页面实例 letprevPage=pages[pages.length-2];//上一页页面实例 if(prevPage.$vm.info.SN!=undefined){ prevPage.$vm.info.SN=str; ......
  • java 泛型作为方法的返回值的封装
    问题背景业务需要,经常需要http方式调用某服务,然后某服务返回特定类型的返回内容。类似StringresStr=xxxHttpClient.post(),然后它返回一个字符串,你还需要反序列化成某种格式的。返回值可以反序列化成的形式如下:{ privateStringcode;privateStringmessage; //这......