我的编程空间,编程开发者的网络收藏夹
学习永远不晚

VUE学习之Element-ui文件上传实例详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

VUE学习之Element-ui文件上传实例详解

引言

对于文件上传,在开发主要涉及到以下两个方面:

单个文件上传和表单一起实现上传(这种情况一般都是文件上传之后,后端返回保存在服务器的文件名,最后和我们的表单一起上传)

单文件上传

element-ui中的el-upload组件默认发送post请求,在使用upload组件自动携带的请求方式发送。因此详情可参考elenent-ui官网 Element-UI官网

以下使用手动上传着重介绍一下el-upload的一部分属性参数

<el-upload
  class="upload-demo"
  ref="upload"
  action="https://jsonplaceholder.typicode.com/posts/"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :auto-upload="false"
  list-type="picture">
  <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
  <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<script>
  export default {
    data() {
      return {
        fileList: []
      };
    },
    methods: {
      handleRemove(file, fileList) {
        console.log(file, fileList);
      },
      handlePreview(file) {
        console.log(file);
      },
      submitUpload() {
        this.$refs.upload.submit();
      },
    }
  }
</script>
  • data 上传时可携带的参数,这里后台用map接收
  • file-list 上传的文件列表, 例如: [{name: ‘food.jpg’, url: ‘https://xxx.cdn.com/xxx.jpg’}]
  • on-success 上传成功之后的钩子,可以用来清除表单校验和文件列表
  • on-error 上传失败之后的钩子
  • auto-upload 是否在选取文件后立即进行上传,默认为true,会自动上传,false取消自动上传
  • list-type 文件列表的类型 text/picture/picture-card 默认text
  • on-preview 点击文件列表中已上传的文件时的钩子
  • on-change 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
  • slot=“trigger” 触发文件选择框的内容
  • slot=“tip” 提示说明文字

和表单一起上传

需求:需同时给后端传文件FormData和其他所需参数

实现方法一:

关键点:el-upload的http-request方法获取文件File信息和FormData方式传参

http-request :覆盖默认的上传行为,可以自定义上传的实现;函数的参数里包含file对象filename字段action字段,以及onProgress,onSuccess,onError三个函数,可以在自定义上传中,在不同时机调用这些函数,会触发upload组件传入的上传钩子函数

<!-- 文件上传-->
<el-form :rules="rules" :model="dataForm" ref="dataForm" label-width="150px" @submit.native.prevent>
      <el-form-item label="名称:" prop="name">
        <el-input type="text" v-model.trim="dataForm.name" clearable></el-input>
      </el-form-item>
      <el-form-item label="文件:" prop="file" >
        <el-upload
            class="upload-import"
            ref="uploadImport"
            :http-request="httpRequest"
            action=""
            :on-remove="handleRemove"
            :file-list="fileList"
            :limit="1" <!-- 限制上传数量-->
            :on-change="handleChange"
            :auto-upload="false"	<!-- 关闭自动上传-->
            accept="application/zip,.zip">  <!-- 设置接收的文件类型-->
          <el-button v-show="!hasFile" slot="trigger" size="small" type="primary" >选取文件</el-button>
          <div slot="tip" class="el-upload__tip">只能上传zip文件,且不超过10M</div>
        </el-upload>
      </el-form-item>
      <el-form-item>
         <el-button type="primary" @click="submitUpload">提交</el-button>
         <el-button @click="resetForm('ruleForm')">重置</el-button>
         <el-button @click="dialogFormVisible = false">取 消</el-button>
      </el-form-item>
 </el-form>

<script>
export default {
	data(){
		return {
			dataForm: {
	          name: '',
	          file: null
	        },
	        rules: {
	          name: [
	            {required: true, message: "请输入名称", trigger: "blur"},
	            {max: 50, message: "最长可输入50个字符", trigger: "blur"},
	            {validator: isvalidatName, trigger: "blur" },
	          ],
	          file: [
	            {required: true, message: "请选择上传文件", trigger: "blur"},
	          ]
        },
        hasFile: false,
        fileList: []
	},
	methods: {
		 handleRemove(file, fileList) {
	        if (!fileList.length) {
	          this.hasFile = false;
	        }
	        this.dataForm.file = null;
	      },
	      handleChange(file, fileList) {
    	    if (fileList.length >= 2) {
	          return;
	        }
	        if (fileList.length === 1) {
	          this.hasFile = true;
	        }
	        this.dataForm.file = file;
	      },
	      //确定按钮
	      //调用组件upload的submit方法,从而触发httpRequest方法,实现手动上传
	      submitUpload() {
	      	this.$refs.dataForm.validate(valid => {
	      		if(vaild){
	      			this.$refs.uploadImport.submit();
	      		}
			})
    	  },
    	  httpRequest(param) {
	    	  let fd = new FormData();
		      fd.append('file', param.file); // 传文件
		      fd.append('name',  dataForm.name); 
		      //dataPar.file.raw
		      axios.post('/interface/importProject', fd , {
				headers: {'Content-Type': 'multipart/form-data'},//定义内容格式,很重要
				timeout: 20000,
			  }).then(response => {
				console.log(res)
			    //接口成功调用params上的onSuccess函数,会触发默认的successHandler函数
          		//这样可以用自带的ui等
          		///params.onSuccess({name: 'eric'})
			    }).catch(err =>{})						
		      }
			})
   		 }
	}
}
</script>

实现方法二:

关键点:把表单数据作为上传时附带的额外参数提交给后台就好了。

<el-dialog title="添加歌曲" :visible.sync="dialogFormVisible">
   <el-form :model="form" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
     <el-form-item label="曲名" prop="name">
       <el-input v-model="ruleForm.name"></el-input>
     </el-form-item>
     <el-form-item label="专辑" prop="introduction">
       <el-input  v-model="ruleForm.introduction"></el-input>
     </el-form-item>
     <el-form-item label="歌词" prop="lyric">
       <el-input type="textarea" v-model="ruleForm.lyric"></el-input>
     </el-form-item>
     <el-form-item label="歌曲文件" prop="introduction">
       <el-upload
		   ref="upload"
		   :action="url" 
		   :limit="2"
		   multiple
		   :with-credentials="true"
		   :on-success="upFile"
		   :on-remove="handleRemove"
		   :on-exceed="handleExceed"
		   :data="upData"
		   :auto-upload="false"
		   accept=".KEY, .CRT">
		   <img class="lazy" data-src="/static/images/web/upload.png" alt>
		    <span>选择上传文件</span>
		   <div slot="tip" class="el-upload__tip">只能上传.key/.crt文件,且只能上传两个</div>
		 </el-upload>
     </el-form-item>
     <el-form-item>
       <el-button type="primary" @click="submitUpload">提交</el-button>
       <el-button @click="resetForm('ruleForm')">重置</el-button>
       <el-button @click="dialogFormVisible = false">取 消</el-button>
     </el-form-item>
   </el-form>
</el-dialog>
data() {
    return {
      url: service.defaults.baseURL + "aaa/bbb", // 这里写上传文件的地址
      form: {
        name: "",
        introduction: "",
        lyric: "",
      }
    };
  },
computed: {
   // 这里定义上传文件时携带的参数,即表单数据
    upData: function() {
      return {
        body: JSON.stringify(this.form)
      }
    }
  },
methods: {
  add(form) {
    this.$refs[form].validate(async valid => {
      if (valid) {
      // 表单验证通过后使用组件自带的方法触发上传事件
        this.$refs.upload.submit()
      } else {
        return false;
      }
    });
},
  // 成功上传文件
  upFile(res, file) {
    if (res.status == 200) {
      // 文件上传成功后的回调,比如一些提示信息或者页面跳转都写在这里
      this.$message.success(res.info);
    } else {
      this.$message.warning(res.info);
      let _this = this;
      setTimeout(function() {
        _this.$refs.upload.clearFiles();
      }, 1000);
    }
  },
 // 上传文件超出个数
  handleExceed(files, fileList) {
    this.$message.warning(`当前只能选择上传2 个证书`);
  },
 //  移除文件
 handleRemove(res, file, fileList) {
   this.$message.warning(`移除当前${res.name}证书,请重新选择证书上传!`);
 }
}

因为文件上传使用的是Content-Type: multipart/form-data;携带参数使用的是FormData格式,我们需要把表单数据转换一下格式,后台才能接收到。

将body的格式进行转换一下:

  • JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串
  • JSON.parse()可以将JSON字符串转为一个对象。

数据的编码方式

在此之前可以先了解一下文件上传的编码方式

http协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python ,java等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。

前端HTTP发POST请求携带参数与后端接口接收参数

补充:代理的使用

action:代表上传的地址,在开发中一般写成动态绑定的属性,在计算属性中决定其最终值。

<el-upload
  :action="uploadURL">
</el-upload>
<script>
  export default {
    data() {
      return {
        uploadURL: '',
      };
    },
    computed: {
	    uploadURL() {
	      if(process.env.NODE_ENV === 'production'){
	        return '/api/uploadFile'
	      }
	      return '/dev-api/api/uploadFile'
	    }
  	}
  }
</script>

为什么要区分运行环境来使用不同的url?因为开发环境配置了代理

 proxy: {
    [REQUEST_PRE]: {
       target: 'http://localhost:88',
       changeOrigin: true,
       secure: false,
       pathRewrite: {
         ['^' + process.env.VUE_APP_BASE_API]: ''
       }
    },    
 }

而这个值在开发环境中是"/dev-api",在生产环境是“/”

所以开发环境需要在开头加上"/dev-api",生产环境则不需要

那为什么只有这一个要单独处理,其他的url不需要呢?因为其他的url是通过axios请求的,axios中配置了baseUrl,所以其他的url不需要单独处理了

什么是代理?为什么要用代理

因为开发环境是配置了代理的,代理就是通过一个特殊的网络服务去访问另一个网络服务的一种间接访问方式。像我们不能直接访问国外的网站,只能使用VPN,就是是使用了代理。

那么前端为什么要代理?

  1. 前端应用的要能访问,那必须是放在服务器上,(服务器可以是nginx、node.js、apache、tomcat等),我们本地vue开发就是用nodejs启动了一个服务。
  2. 由于浏览器的同源策略(协议,IP,端口号都相同为同源),禁止网站向非同源的服务器发送ajax异步请求,也就是跨域。

因此使用代理来解决跨域问题

代理的使用

Vue代理配置

vuecli3的代理设置在vue.config.js->devServer->proxy

vite构建的vue代理设置在 vite.config.js->server->proxy

(Vite 是 vue 的作者尤雨溪在开发 vue3.0 的时候开发的一个 基于原生 ES-Module 的前端构建工具)

他们的代理配置是一样的,这里以vuecli3为例:

const REQUEST_PRE = "/api"
module.exports = {
	// 其他配置省略
	
	// 本地代理配置
	devServer: {
		// 默认是false,可以将http://localhost:8080 变为 https://localhost:8080
        https: true,
        // 代理配置
        proxy: {
        	// 简单写法
        	"/normal":{
        		target: 'http://localhost:80',
        		ws: true,  // 允许websocket代理
                changeOrigin: true //允许跨域
        	},
        	
        	// 变量写法
            [REQUEST_PRE]: {
                target: 'http://localhost:88',
                ws: true,
                changeOrigin: true
            },
            
            // 重写,当访问http://localhost:80/req/getData
            // 实际上访问的是 http://localhost:8888/module/getData
            '/req': {
                target: 'http://localhost:8888',
                pathRewrite: path => path.replace('/req', '/module'),//replace方法返回一个替换好的新的字符串
                ws: true,
                changeOrigin: true
            },
        },
        open: true
    }
}

注意(坑点):

1、后面的反斜杠要保持一致,虽然对接口调用没有影响,但是对代理文件的相对路径有影响

如 /req,target就写 http://localhost:8888

如 /req/,target就写 http://localhost:8888/

2、不管是vuecli还是vite,同前缀代理是有前后顺序的,只生效前面的

比如当你调用 localhost:8080/api/other/getData

下面的写法会代理到 8888

'/api': 'http://localhost:8888',
'/api/other': 'http://localhost:88'

下面的写法会代理到 88

'/api/other': 'http://localhost:88',
'/api': 'http://localhost:8888'

接口调用

const REQUEST_PRE = '/api'
axios.get({
	url: `${REQUEST_PRE}/getData`
}).then(res=>{
	console.log(res)
})

3、pathRewrite:对象/函数,重写目标的 url 路径。对象键将用作正则表达式来匹配路径。

// 重写路径
pathRewrite: { '^/old/api' : '/new/api' }

// 删除路径
pathRewrite: { '^/remove/api' : '' }

// 添加基本路径
pathRewrite: { '^/' : '/basepath/' }

// 自定义重写
pathRewrite: function  ( path ,  req )  {  return  path . 替换('/api' , '/base/api' ) }

// 自定义重写,返回 Promise 
pathRewrite: async  function  ( path ,  req )  { 
  const  should_add_something  =  await  httpRequestToDecideSomething ( path ) ; 
  if  ( should_add_something )  path  +=  "something" ; 
  返回 路径;
}

Proxy文档参考地址

process.env.NODE_ENV

  1. process 是 node 的全局变量,并且 process 有 env 这个属性,但是没有 NODE_ENV 这个属性
  2. NODE_ENV这个变量并不是 process.env 直接就有的,而是通过设置得到的。这个变量的作用是:我们可以通过判断这个变量区分开发环境或生产环境。
  3. 当我们设置 mode 为 development 或者 production时,webpack会自动的进行一些设置
mode: development --> process.env.NODE_ENV = development
mode: production --> process.env.NODE_ENV = production

默认情况下 --> process.env.NODE_ENV = production

总结

到此这篇关于VUE学习之Element-ui文件上传详解的文章就介绍到这了,更多相关VUE Element-ui文件上传内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

VUE学习之Element-ui文件上传实例详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

VUE学习之Element-ui文件上传实例详解

今天进行了element 文件上传组件的运用,写一下心得,下面这篇文章主要给大家介绍了关于VUE学习之Element-ui文件上传的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2022-11-13

vue+element-ui+axios多文件上传怎么实现并显示整体进度

今天小编给大家分享一下vue+element-ui+axios多文件上传怎么实现并显示整体进度的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一
2023-06-29

Android实现上传文件到服务器实例详解

本实例实现每隔5秒上传一次,通过服务器端获取手机上传过来的文件信息并做相应处理;采用Android+Struts2技术。一、Android端实现文件上传 1)、新建一个Android项目命名为androidUpload,目录结构如下:2)、
2022-06-06

JS实现可恢复的文件上传示例详解

这篇文章主要为大家介绍了JS实现可恢复的文件上传示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-29

Blob对象实现文件上传下载示例详解

这篇文章主要为大家介绍了Blob对象实现文件上传下载示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-04

el-upload大文件切片上传实现示例详解

这篇文章主要为大家介绍了el-upload大文件切片上传实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-15

JavaScript基础之文件上传与下载的实现详解

这篇文章主要为大家详细介绍了JavaScript实现文件上传与下载功能的相关资料,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
2023-01-30

使用Spring boot + jQuery上传文件(kotlin)功能实例详解

文件上传也是常见的功能,趁着周末,用Spring boot来实现一遍。前端部分前端使用jQuery,这部分并不复杂,jQuery可以读取表单内的文件,这里可以通过formdata对象来组装键值对,formdata这种方式发送表单数据更为灵活
2023-05-31

Android OkHttp Post上传文件并且携带参数实例详解

Android OkHttp Post上传文件并且携带参数 这里整理一下 OkHttp 的 post 在上传文件的同时,也要携带请求参数的方法。 使用 OkHttp 版本如下:compile 'com.squareup.okhttp3:ok
2022-06-06

Vue组件之间的参数传递与方法调用的实例详解

这篇文章主要介绍了Vue组件之间的参数传递与方法调用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-12-08

Android编程之在SD卡上进行文件读写操作实例详解

本文实例讲述了Android编程之在SD卡上进行文件读写操作的方法。分享给大家供大家参考,具体如下: 很多知识只有真正理解掌握之后才能运用自如,举一反三。对Java中的文件操作和android系统SD卡里面的文件操作,你觉得有区别吗,显然没
2022-06-06

编程热搜

目录