关于React中上传头像 / 图片的那点事, 这样做就对了

项目需求:
React中实现用户头像的上传,可能有人就说了,网上针对头像上传的库简直不要太多哦,什么AntDesign、Material等等. 但是为了一个小小的上传需求就将一个很大的库引入到项目中, 是不是有点欠妥.

先上最终实现图:在这里插入图片描述

最开始考虑的是用html原生的 <input type="file" />方式, 但是在尝试的过程中,发现涉及到各种上传七牛凭证、图片过大涉及的裁剪、图片尺寸的范围设置等. 决定还是放弃这种原生操作实现方式.

于是开始在网上找有没有造好的轮子可以用, 找了好几个,发达不是库很大就是不合适,最后 同事推荐了一个plupload这个库, 网上搜了一下,发现对es6的支持也很好, 决定开始尝试这种上传方式,而且plupload对图片的大小限制,裁切都做了处理,真的很方便.

但没有找到关于在React中上传头像/图片的文章, 索性就自己摸索写一个大概的用例出来给需要的小伙伴做个参考.


参考来源:
1_官网(更多的需求请到官网看document): https://www.plupload.com/

2_pulpload部分中文文档: http://www.bubuko.com/infodetail-909829.html

3_参考项目: https://github.com/ProjectForLearnNodejs/qiniu-nodejsSDK-plupload_real_fileup

关于plupload的参数介绍,可以参考上面参考来源的 1、2 两条, 里面有一些基本的语法使用介绍.


好,言归正传,我们开始尝试入手:


首先 需要

install plupload: > npm i plupload

安装完成之后, 就可以在你的项目文件中,进行使用和操作了.

在项目文件中, 需要在文件头部引入: import plupload from 'plupload'

// 部分示例代码如下:
constructor(props) {
  super(props)
  this.state = {
    filePhoto: this.props.baby.photo_url || null,
  }
}
// 这里我在推荐另一种写法, 如果你不需要在构造函数中 处理其他的数据,只是想初始化用户数据而已, 那么可以使用`属性初始化`方式来简化你的代码:
// 如:
state = {
  filePhoto: this.props.baby.photo_url || null,
}

render() {
  return (
    <div id="user-photo">
      // 这里的id值是必须要的, 否则取不到
      // uploadDefaultPhoto 是用户没上传头像时 import进来的默认头像
      <img src={this.state.filePhoto || uploadDefaultPhoto} />
    </div>
  )
}

然后在文件里写一个上传的方法,此处我们就起名叫: initSinglePlupload

initSinglePlupload = () => {
  var uploader = new plupload.Uploader({//创建实例的构造方法
    runtimes : 'html5, flash',//上传插件初始化选用那种方式的优先级顺序
    browse_button: 'user-photo', // 上传按钮 引发上传事件的按钮的id
    url: "https://upload.qiniup.com",   //远程上传地址 后台地址
    filters : {
      max_file_size : '10mb', //最大上传文件大小(格式100b, 10kb, 10mb, 1gb)
      mime_types: [
        {title : "JPG/PNG文件", extensions : "jpg,jpeg,JPG,JPEG,png,PNG,gif,GIF"}
      ]
    },
    multi_selection: false,   //true多文件上传, false 单文件上传
    multipart_params : { 
      // 需要的token值,这个token我在componentDidMount中对token值做了处理了,所以这里不需要在带值过去了
      token: ''
    },
    multipart: true, //为true时将以multipart/form-data的形式来上传文件
    resize: {
      width: 1600,
      height: 1600
    },
    init: {
      // 注: FilesAdded方法我放到componentDidMount中做了,然后在componentDidMount中做了init的调用,这么做是因为是想要在页面刷新完之后,点击上传图标就可以很及时的拿到上传所需要的token值
  // FilesAdded: function (uploader, files) { //文件上传前
  //   this.toast = ToastManager.showLoading("图片上传中...");
  //   uploader.start();
  // },
  FileUploaded: function (up, file, result) { //文件上传成功的时候触发
    // 图片上传成功之后, 本地不会异步执行state值, 把头像替换,所以这里需要reload一遍页面
    // 然后后端会重新返回头像链接,这时候img中再去取头像即可

    location.reload() 
    this.toast.cancel()
  },
  Error: function (up, err) { //上传出错的时候触发
    this.toast.cancel() // 隐藏 图片上传loading..
  }
}
  });
  return uploader
}

// 页面初始化全部加载完
   componentDidMount() {
     // 获取后端返回的token url
     var generate_token_url = this.props.generate_token_url
     
     var uploader = this.initSinglePlupload('')
     uploader.bind('FilesAdded',function(uploader, file) {
       this.toast = ToastManager.showLoading("图片上传中...");
       
       // 说明, 下面的`request`是我在axios的基础上做的一个请求封装, 如果你没有封装, 直接用axios的方式操作也是没有问题的.
       
       request({
         url: generate_token_url, // 友情提醒: generate_token_url必须要放到 uploader.bind上面去定义.否则拿不到值
         method: "GET",
         params: {
           type: 'baby'
           // 这里的参数根据 自己项目来判断传什么样的参数
           // 因为我当前针对的是宝宝信息页面的头像上传,所以这里和后端商量之后,传'baby'给后端
         },
         headers: csrfHeaders // 跨域处理
       }).then(res => {
         // 下面log里面打印的是从七牛请求链接中拿到的token值,这个值必需要,是为了上传凭证,给七牛做校验
         // console.log(res.data.token)
         
         uploader.setOption('multipart_params', {
           token: res.data.token  // 上传凭证
         })
   
         uploader.start() // 调用实例对象的start()方法开始上传文件,当然你也可以在其他地方调用该方法
       }).catch(err => {
         Raven.captureException(err)
         this.toast.cancel()
       })
     })
     uploader.init(); //在实例对象上调用init()方法进行初始化
   }

看到这里, 差不多就结束了, 自己根据network中的返回值和状态码来判断哪里处理问题,在处理下;

通过以上的方式操作, 基本上就实现了,在React中上传头像的操作了;

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值