Vue实现手动ajax上传并将文件转成Base64编码字符串传给后端

最近初学vue项目中要用到上传功能,因为element-ui默认通过action上传,不够灵活,看了官方文档之后,改用其中属性http-request实现自定义上传(http-request: 覆盖默认的上传行为,可以自定义上传的实现)

前端计算MD5 可以使用插件 js-spark-md5,下载 spark-md5.min.js 存储在本地。

这里还应用到了大多数浏览器都实现了的类 FileReader,它的实例的 readAsDataURL方法,用来读取文件的base64编码以表示所读取文件的内容。FileReader——readAsDataURL

先贴一下element-ui Upload 上传的属性

参数说明类型默认值
action必选参数,上传的地址string
headers 设置上传的请求头部object
multiple 是否支持多选文件boolean
data上传时附带的额外参数object
name上传的文件字段名stringfile
with-credentials支持发送 cookie 凭证信息booleanfalse
show-file-list是否显示已上传文件列表booleantrue
drag是否启用拖拽上传booleanfalse
accept接受上传的文件类型(thumbnail-mode 模式下此参数无效)string
on-preview点击文件列表中已上传的文件时的钩子function(file)
on-remove文件列表移除文件时的钩子function(file, fileList)
on-success文件上传成功时的钩子function(response, file, fileList)
on-error文件上传失败时的钩子function(err, file, fileList)
on-progress文件上传时的钩子function(event, file, fileList)
on-change 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用function(file, fileList)
before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。function(file)
before-remove删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。function(file, fileList)
list-type文件列表的类型stringtext/picture/picture-card
auto-upload是否在选取文件后立即进行上传booleantrue
file-list上传的文件列表, 例如: [{name: ‘food.jpg’, url: ‘https://xxx.cdn.com/xxx.jpg’}]array
http-request覆盖默认的上传行为,可以自定义上传的实现function
disabled是否禁用 booleanfalse
limit最大允许上传个数number
on-exceed文件超出个数限制时的钩子function(files, fileList)

element-ui上传代码实现

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<link rel="stylesheet" href="//unpkg.com/element-plus/lib/theme-chalk/index.css">
	<style>
		.text {
		    font-size: 14px;
		  }
		  .item {
		    padding: 18px 0;
		  }
		  .box-card {
		    width: 480px;
		  }
	</style>
	<body>
		<div id="firmwareUpdate">
			<el-divider></el-divider>
			</el-descriptions>
			<el-card class="box-card">
				<div :key="o" class="text item">
					<el-upload class="upload-demo" ref="upload" :on-preview="handlePreview" :on-remove="handleRemove" :on-change="handleChange"
					 :file-list="fileList" :auto-upload="false" :limit="1" :http-request="updateUpload">
						<template #trigger>
							<el-button size="small" type="primary">选取文件</el-button>
						</template>
						<el-button style="margin-left: 10px;" size="small" type="success" @click="updateUpload">上传到服务器</el-button>
						<template #tip>
							<div class="el-upload__tip">
								只能上传一个文件,请不要瞎传!
							</div>
						</template>

					</el-upload>
					<p id="data"></p>
				</div>
			</el-card>
		</div>
	</body>
	<script src="//unpkg.com/vue@next"></script>
	<script src="//unpkg.com/element-plus/lib/index.full.js"></script>
	<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
	<script src="spark-md5.min.js"></script>
	<script>
		var Main = {
			data() {
				return {
					//文件集合
					fileList: []
				};
			},
			methods: {
				updateUpload() {
					//获取文件file对象
					let file = this.$refs.upload.uploadFiles.pop().raw;
					//构造一个FileReader对象
					let reader = new FileReader();
					//readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,	readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
					reader.readAsDataURL(file);
					reader.onload = function(e) {
						var result = this.result;
						//文件的base64编码字符
						var base64 = this.result.substring(this.result.indexOf(',') + 1);
						//计算文件的md5值
						var md5Value = SparkMD5.hashBinary(e.target.result);
						$.ajax({
							headers: {
								Accept: "application/json; charset=utf-8"
							},
							url: url,
							type: 'post',
							async: false, //false 同步  true 异步 
							cache: false, //cache作用:是否在缓存中读取数据的读取。cache属性是true(默认值)时:在第一次请求完成之后,如果地址和参数不变化,第二次去请求,会默认获取缓存中的数据,不去读取服务器端的最新数据。cache属性是flase(默认值)时:每次读取的是最新的数据。
							timeout: 10000, //超时时间设置为10秒;
							dataType: 'json',
							data: {
								base64: base64,
								md5Value: md5Value,
							},
							success: function(data) {
								var msg = data.subCode;
								if (msg == 0) {
									alert("上传成功!");
								} else {
									alert("上传失败!");
								}
							},
							error: function(data) {
								alert("上传失败!");
							}
					});
					}
				},
				//删除触发
				handleRemove(file, fileList) {
					console.log(file, fileList);
				},
				//预览触发
				handlePreview(file) {
					console.log(file);
				},
				//发生改变触发
				handleChange(file, fileList) {
					console.log(file, fileList);
				},
			}
		};
		const app = Vue.createApp(Main);
		app.use(ElementPlus);
		app.mount("#firmwareUpdate")
	</script>
</html>

文章仅用作记录分享,若有不当,还望指正。

最近开通个人了微信公众号,以后将会定期分享工作学习过程中遇到的问题,欢迎关注与我一道成长交流~:

微信搜索: MYY668999程序猿爱篮球 即可上车。

Logo

前往低代码交流专区

更多推荐