写给自己的文件上传攻略以及el-upoad使用详解

文件上传的原理
原理很简单,就是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。
如果要上传一个文件,需要把 form 标签的enctype设置为multipart/form-data,同时method必须为post方法。
例如:

<form method="post" action="http://localhost:8100" enctype="multipart/form-data">

解释如下:
MIME规定了每一个资源的类型,我们通过MIME判断资源类型。
multipart/form-data
我们通过Content-Type HTTP Header 头来知晓每种资源的MIME类型。当客户端发送了一个 “Content-Type: multipart/form-data;”,代表客户端要上传一个附件。也就是说 Content-Type 后面的值就是一个 MIME 类型。
含义:multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件。

消息体什么意思呢,如果你自行想使用代码实现文件上传,要根据定义自行封装HTTP消息,接下去我们简单描述一下。
请求头
Content-Type: multipart/form-data; boundary=——FormBoundary 表示要上传附件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———FormBoundary开始,以———FormBoundary结尾。每一个表单项又由Content-Type和Content-Disposition组成。

例如:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次请求要上传文件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———XXX开始,以———XXX结尾。

Content-Type:表示当前的内容的 MIME 类型,是图片还是文本还是二进制数据。
Content-Disposition HTTP 消息头:其中第一个参数总是固定不变的form-data,name表示表单元素属性名,回车换行符后面的内容就是元素的值。
客户端发送请求到服务器后,服务器会收到请求的消息体,然后对消息体进行解析,解析出哪是普通表单哪些是附件。一般情况下不需要自行解析,目前已经有很成熟的三方库可以使用。

最初进行文件上传的方式是:
1:表单上传:

<form name="form名称" action="请求地址"  method="请求类型" enctype ="multipart/form-data">
    <input type="file" name="">
    <input type="text" name="">
    <input type="submit" value="提交">
</form>

2:使用使用FormData对象 配合ajax

 let form_data = new FormData();
 $.ajax({
      url: url,
      type: method,
      data: formData,
      processData: false,
      contentType: false,
      xhrFields: {
        withCredentials: true
      },
      crossDomain: true,
      success: function (obj) {
        // ...
      },
      error: function (obj) {
        // alert('服务器请求失败');
      }
    })

3,使用表单插件,例如jquery.form.js

// ajaxSubmit提交form表单
  function updateUserInfo() {
    $('#表单ID').ajaxSubmit({
      url: url,
      type: 'POST',
      //data: $('表单ID').serialize(),
      //processData: false,
      //contentType: false,
      xhrFields: {
        withCredentials: true
      },
      crossDomain: true,
      success: function (obj) {
        // ...
      },
      error: function (obj) {
        // alert('服务器请求失败');
      }
    });
  }

使用el-upload实现文件上传
原理:
请求头中加token令牌

:headers="authHeaders"
data中声明
authHeaders: {},
//在请求头中加token,放在created中
this.accessToken = this.$store.getters.accessToken; this.authHeaders["Authorization"] = "Bearer " + this.accessToken;

在action中设置接受url地址。

:action="uploadUrlReferrer({type:'附件证明'})"
uploadUrlReferrer (row) {
        let url = `${this.expertApiUrl}/experts/${this.expert.referrerId}/expert/${
          row.type
          }`;
        return url;
      },

至此,上传功能已经完成了。文件在点击上传之后,会自动获取本地文件列表,选择文件之后会上传至数据库。当然,这需要后端的配合,我只写了前端的部分。前端和后端的分界线就是url。

如果要用axios实现文件上传,需要使用before-upload 钩子, 用before-upload 自己上传 想怎么传都可以

删除文件
需要使用on-remove钩子

:on-remove="handleRemoveTwo"

钩子绑定函数,函数实现功能,因为项目比较大,其他地方也需要使用重复获取文件的功能,所以为了实现复用,将这部分放到了函数getExpertDocsFile()中。

调用deleteDoc接口,提供文件id,实现删除,删除完成之后,再重新获取文件列表。

handleRemoveTwo (file, fileListTwo) {
        deleteDoc(this.expert.referrerId, file.id).then(res => {
          if (res.status == 200) {
            this.$message({
              message: "操作成功",
              type: "success"
            });
            this.getExpertDocsFile();
          }
        })
      },
getExpertDocsFile () {
        let that = this;
        that.fileListTwo = [];
        //getExpertDocs是获取包含附件的表的一个接口,接口传入的参数是专家的referrerId值,这个函数的目的是将数据库的获取到的函数push到fileListTwo中,使得附件显示出来,这里的fileListTwo也是一个钩子对应的值。`:file-list="fileListTwo"`这个钩子就是el-upload要显示在页面的文件列表,需要和数据库做对应。
        
        getExpertDocs(that.expert.referrerId).then(res => {
          that.docs = res.data || [];
          if (that.docs.length > 0) {
            _.map(that.docs, doc => {
              if (doc.type == '附件证明') {
                that.fileListTwo.push(doc);
              }
            });
          }
        });
        var referrerExpert = that.expertsSelect.filter(a => {
          return a.id == that.expert.referrerId
        });

        if (referrerExpert && referrerExpert.length > 0) {
          that.referrerPaid = referrerExpert[0].referrerPaid;
        }
      },

预览(下载)文件
使用on-preview这个钩子,使用window.open打开文件,url是根路径和文件路径拼接而成。

:on-preview="handlePreview"
handlePreview (file, fileListTwo) {
        let base = this.expertFileUrl;
        let docUrl = base + file.path;
        window.open(docUrl);
      },

多文件上传
在组件中加一个multiple属性
禁止操作
disabled
我这里限制了referrerPaid为true时限制上传操作,但此时按钮并不会变灰,若想要按钮变灰无法操作,需要在按钮上也加一个disabled

:disabled="referrerPaid"

限制文件上传个数
imit限制数量为3,超出限制数量之后触发handleExceed函数

:limit="3"
:on-exceed="handleExceed"
handleExceed (files, fileList) {
        this.$message.warning(
          `当前限制选择 3 个文件,本次选择了 ${
            files.length
            } 个文件,共选择了 ${files.length + fileList.length} 个文件`
        );
      },

其他优化——类型大小限制

(1)一种方式是,加accpet属性

<el-upload class="upload-demo" :multiple="true" :action="action" accept="image/jpeg,image/gif,image/png,image/bmp" 
:file-list="fileList" :before-upload="beforeAvatarUpload" :on-success="handleAvatarSuccess">

(2)另一种方式是在上传前的触发函数里面去判断
beforeUpload钩子中触发的函数

beforeAvatarUpload(file) {
    const isJPG = file.type === 'image/jpeg';
    const isGIF = file.type === 'image/gif';
    const isPNG = file.type === 'image/png';
    const isBMP = file.type === 'image/bmp';
    const isLt2M = file.size / 1024 / 1024 < 2;

    if (!isJPG && !isGIF && !isPNG && !isBMP) {
        this.common.errorTip('上传图片必须是JPG/GIF/PNG/BMP 格式!');
    }
    if (!isLt2M) {
        this.common.errorTip('上传图片大小不能超过 2MB!');
    }
    return (isJPG || isBMP || isGIF || isPNG) && isLt2M;
},
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值