zoukankan      html  css  js  c++  java
  • 微信小程序开发技巧总结(二) -- 文件的选取、移动、上传和下载

    微信小程序开发技巧总结(二) -- 文件的选取、移动、上传和下载

    1.不同类型文件的选取

    1.1 常用的图片 视频

    对于大部分开发者来说,需要上传的文件形式主要为图片,微信为此提供了接口。

    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success (res) {
        // tempFilePath可以作为img标签的src属性显示图片
        const tempFilePaths = res.tempFilePaths
      }
    })
    

    其次为视频文件的选取,微信也为此提供了接口。

    wx.chooseVideo({
      sourceType: ['album','camera'],
      maxDuration: 60, //视频长度 单位 s
      camera: 'back', //选取前置  摄像 还是 后置 摄像
      success(res) {
        console.log(res.tempFilePath)
      }
    })
    

    也为其提供了视频和图片的二合一接口,这个接口不建议调用,图片和视频的上传建议区分开。

    wx.chooseMedia({
      count: 9,
      mediaType: ['image','video'],
      sourceType: ['album', 'camera'],
      maxDuration: 30,
      camera: 'back',
      success(res) {
        console.log(res.tempFilePath)con
        console.log(res.size)
      }
    })
    

    这几个接口调用成功的回调函数中,都返回的是文件在文件在本机中的路径。

    res.tempFilePath
    

    这是一个 数组,存放着选择的所有文件的路径,用于上传。

    1.2 其余形式各种文档

    那么如果是想要在小程序中上传 doc、pdf、ppt 等类型的文件怎么处理?首先要注意的是微信小程序并没有给用户提供文件管理器接口。

    开发者:我想要个文件管理器接口!

    官方:不,你不想

    聪明的开发者他没有办法,只能另辟蹊径。微信提供了一个选择客户端会话文件的方法。

    wx.chooseMessageFile({
       success(res){
           console.log(res.tempFilePath)
        }
    })
    

    与上面两个接口相同,返回的也是文件在本地的存储路径,但是不同的是,这个接口可以选取全部的文件类型。

    开发者如果想要上传非图片和视频内容的话,需要两步走。

    1. 打开微信文件传输助手,将想要上传的文件发送到文件传输助手
    2. 在小程序中调用这个接口,选择文件传输助手,从会话中选择想要上传的文件。

    2.文件的上传

    2.1 uploadFile方法

    所有的文件都是以字节流的形式进行上传,所以上传形式并没有什么本质区别,都是调用相应的接口进行上传。

    小程序端写法如下:

    wx.uploadFile({
          url: '你的服务器函数地址', //仅为示例,非真实的接口地址
          filePath: '需要上传的文件路径', //res.tempFilepaths
          name: 'file', // 文件对应的key ,默认 为 file
          formData: {
            'user': 'test'
          }, //上传额外携带的参数
          success (res){
            const data = res.data
            //do something
          }
    })
    

    2.2 服务器端如何处理上传的文件

    服务端如何接受文件的上传?仅展示Java方式(SpringBoot 框架)

    @Controller
    @ResponseBody
    public class FileController {
        //文件上传控制类,是核心配置类,Win <->Linux
        @RequestMapping(value = "/upload/images")
        public String uploadimages(HttpServletRequest request,@RequestParam("file") MultipartFile file, @RequestParam("user") String user) throws IOException {
           //更换服务器,这个值也需要修改
            //图片上传写法
            //type 是上传图片的类型
            if(!file.isEmpty()){
                //文件不为空
                //String path = "E:"+File.separator+"images"+File.separator+type; // this is windows method
                String path = "/share"+File.separator+"images"+File.separator+type;
                // this is Linux method
                String filename = file.getOriginalFilename();
                File filepath = new File(path,filename);//新建文件存储路径
                System.out.println(filepath);
                if(!filepath.getParentFile().mkdirs()){
                    filepath.getParentFile().mkdirs();
                }
                file.transferTo(new File(path+File.separator+filename));
               //想要返回可直接访问的链接还要配置 映射,具体请看下面链接
                return "你的IP地址"+"/images/"+type+"/"+filename;
            }else {
                return "error";
            }
        }
    }
    

    配置访问映射

    文件访问映射

    2.3 云开发文件上传

    微信小程序支持云开发,其文件上传接口有一些差异,但是不需要自己再构建后台。

    wx.cloud.uploadFile({
      cloudPath: 'file/' + '你的文件名字(带格式后缀)', // 在云端存储的路径
      filePath: '', // 就是选择文件返回的路径
    }).then(res => {
      // get resource ID
      console.log(res.fileID)
    }).catch(error => {
      // handle error
    })
    

    我们可以根据返回的fileID 置换 真实的文件访问地址。

    其置换方式参见官方文档:

    wx.cloud.getTempFileURL({
      fileList: ['cloud://xxx', 'cloud://yyy'],
      success: res => {
        // get temp file URL
        console.log(res.fileList)
      },
      fail: err => {
        // handle error
      }
    })
    

    TIPS:关于云开发文件上传的建议

    1. 如果没有保密需求,为了方便后续开发,存储到数据库中的最好是可以直接访问的文件链接。
    2. 置换真实文件地址,不要每次上传一次文件就置换一次,先把返回的fileID 存放在数组中,到该事务所有上传完成后,再使用fileID 数组置换真实文件访问链接数组。
    3. 要考虑文件名重复的可能,建议使用时间戳在 wx.cloud.uploadFile 中的 cloudPath 中对存储到云环境中的文件命名进行格式化。

    总的来说就是先上传文件,再向数据库中写入记录。

    2.4 多文件同时上传的处理方式

    uploadFile 每次只能上传一个文件

    如何处理这个问题?

    A.不考虑文件的上传次序问题,可以采用遍历上传的方式,采用精确的时间戳和遍历index对文件名进行格式化。通过定时触发检测函数判断是否全部上传完成。这种方式考虑的是并发能力。

    upSeveralfiles() {
          wx.showLoading({
            title: '上传中~',
            mask: true
          })
          var that = this;
          var timecode = sev.vcode(new Date()); // 这是时间戳编码函数
          var files = this.data.fileList;       // 这是 选择文件中返回的 res.tempFilePath 数组
          var len = files.length;
          var i = 0;
          for (i = 0; i < len; i++) {
            var str = files[i].name;
            wx.cloud.uploadFile({
              cloudPath: 'file/' + '(' + sev.getformatTime(new Date()) + ')' + str,
              filePath: files[i].path,
              success(res) {
                console.log(res)
                that.setData({
                  cloudlist: that.data.cloudlist.concat([res.fileID]),
    
                })
                 // cloudlist 是存放 文件链接置换id 的数组 , 非云开发存储的就是真实可访问的链接数组
                 // 如果使用的不是云开发 那么 可以返回真实的 访问地址
              },
              fail(res) {
                console.log(res)
              }
            })
          }
        // 使用定时器检测文件是否全部上传完成 , 并 判断是否进行下一步 操作
          var timer = setInterval(function () {
            if (that.data.cloudlist.length == len) {
              // 只有全部上传成功了 长度才会相等
              clearInterval(timer);
              // 继续执行下一步 ,根据 cloudlist 置换真实地址 并存放到数据库
              // 如果使用的非云开发,那么就继续执行 存储至数据库的操作
            }
          }, 1000)
       }
    

    补充文件编码函数 sev.js 中的根据时间编码部分 , 可以根据实际流量自定义。

    function getformatTime(date) {
      var year = date.getFullYear()
      var month = date.getMonth() + 1
      var day = date.getDate()
    
      var hour = date.getHours()
      var minute = date.getMinutes()
      var second = date.getSeconds()
    
      return [year, month, day].map(formatNumber).join('-');
    };
    

    B.考虑文件的上传次序问题,采用回调方式进行文件上传(更推荐使用这种方式)

    data: {
        fileList: [],
        realList: [],//云端地址链接列表
        fileid: 0,
     },
    upSeveralfiles() {
        var that = this;
        var files = this.data.fileList;       // 这是 选择文件中返回的 res.tempFilePath 数组
        var len = files.length;
        var uid = this.data.fileid;
        wx.uploadFile({
          url: '你的服务器文件接收函数请求地址',
          name: 'file',
          filePath: files[uid],
          header: {
            "Content-Type": "multipart/form-data"
          },
          success(res) {
            that.setData({
              fileid: uid + 1,
              realList: that.data.realList.concat([res.data])
            }, () => {
              if (that.data.fileid == len) {
                // 上传完成 ,执行下一步操作
                  
              } else {
                  //上传完一个文件 递归执行 下次上传
                that.upSeveralfiles();
              }
            })
          }, fail(res) {
            console.log(res.data)
          }
        })
    
      },
    

    以上是提供的两种思路 , 无论是不是云开发 , 两种思路都是共通的,适用于多文件上传.

    3.文件的下载

    这个地方唯一值得注意的是云开发的一种下载方式 可以通过fileID进行download , 当然只能下载存储在自己云环境中的文件.

    wx.cloud.downloadFile({
      fileID: '',
      success: res => {
        console.log(res.tempFilePath)
      },
      fail: err => {
      }
    })
    
    wx.downloadFile({
      url: '', //仅为示例,并非真实的资源
      success (res) {
         //res.tempFilePath
    })
    

    下载进度监控 , 用于下载进度条绘制等功能实现

    const downloadTask = wx.cloud.downloadFile({ *** }) // wx.downloadFile 同理
    downloadTask.onProgressUpdate((res) => {
        //res.progress 为下载进度
    })
    

    下载下来的文件支持直接打开,就像是在微信聊天中打开一样,需要下载插件。

    其使用方式为:

    wx.openDocument({
         filePath: res.tempFilePath //为文件路径 非数组 , 可使用回调函数 success 等
    })
    

    4.文件的移动

    这个一般情况下是用不到的, 也不建议使用移动文件的方法作为功能实现手段 ,必然有更好的替代方式,比如修改数据库路径 和 真实文件路径的映射, 效率更高一些.

    这里仅讲云开发移动文件方式。

    const cloud = require('wx-server-sdk')
    const fs = require('fs')
    const path = require('path')
    
    cloud.init({
      env: cloud.DYNAMIC_CURRENT_ENV
    })
    
    exports.main = async (event, context) => {
      const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
      //这个可以读取 云存储 中的文件 , 所谓删除 就是复制 然后 删除原位置文件
      return await cloud.uploadFile({
        cloudPath: 'demo.jpg',
        fileContent: fileStream,
      })
    }
    

    具体开发文档

    建议在数据库中修改映射路径最好。

    需要小程序开发的请联系我QQ : 1025584691

  • 相关阅读:
    Sencha的Eclipse插件提示和技巧
    《敏捷软件开发过程及最佳实践》培训总结
    《Sencha应用程序的UI测试 》一文的示例分析
    Ext JS 4.2 Beta版发布
    迅速解决resin或者tomcat启动闪一下就消失的问题
    import javax.servlet 出错
    有爱好者把我的CMS管理系统改成了JAVA版,有兴趣的可以看看
    一个@符号引发的血案:Access数据库无法更新
    Windows 7下如何安装和配置IIS 7和ASP
    .Net中Freetextbox_1.6.3的使用与ftb.imagegallery.aspx安全修正
  • 原文地址:https://www.cnblogs.com/masterchd/p/12319440.html
Copyright © 2011-2022 走看看