最近项目中使用到了图片上传功能,作为前端开发对此应该不陌生,正常来说图片会有一个单独存储的服务,例如现在公司使用minio统一集中管理,直接部署在docker上面非常方便,下面记录一下使用经历过的图片上传
1.base64直接上传
这种base64直接上传给后端,然后后端拿到数据之后就能自行处理,一般前端会对base64数据前面拼接 "data:image/jpeg;base64," + base64数据;代表图片格式,其余后端自行处理,相对来说这种方式对前端更加友好,上传方式跟普通数据上传完全相同,然后后端返回图片存储的相对路径,前端进行拼接ip前缀就能正常展示;如下面代码:
$.ajax({
url: uploadFea,
type: "POST",
dataType: "JSON",
processData: false,
beforeSend: function () {
console.log("正在上传特征值文件,请稍候");
},
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
data: {
platform: "web",
uploadFile: feaFile,
name: fileName + "_" + guid(),
},
success: (res) => {
console.log(res.fileSuccess);
},
});
2.form表单方式的提交
这种是类似于form表单提交,这样其实是类似于element-ui中的上传,本质就是表单上传,而且方法提供的非常全面直接复制就行,这样一般也会有几种情况;
一种是直接提交给后端,一种是传base64数据给后端,还一种情况是前端获取到的图片数据是硬件提供的数据(例如身份证读卡器)一般是直接给你base64数据,但是后端接口不支持直接传base64,这样就需要前端童鞋处理一下base64数据了,然后再以表单提交文件形式传给后端了
1.直接提交给后端就是如下:
<form action="http://192.168.10.94:3050/serverData/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="tupian" multiple="multiple">
<input type="text" name="id" id="name">
<input type="submit"value="提交"id="btnn">
</form>
这是自己本地使用node做的一个简单图片上传接口,接口能接收到文件数据,然后通过重命名移动等操作将处理后的图片文件保存到对应服务器目录,后端能直接获取到文件名称后缀以及数据等信息,自习看下element-ui其实本质就是一个封装好的表单提交,如下:
<el-upload class="avatar-uploader" :style="styles" :http-request="uploadImg" :on-progress="uploadVideoProcess" :disabled="isDisabled">
<el-progress type="circle" v-show="videoFlag" :percentage="videoUploadPercent" class="circle"></el-progress>
</el-upload>
2.element-ui中提供了 :http-request 方法我们能够使用,可以直接上传文件或者上传base64数据如:
//后端不需要base64
uploadImg (file) {
//这里file其实就是上传的文件,如果后端需要此类上传我们就能直接使用
$.ajax({
type: 'post',
url: upLodUrl,
data: file,
dataType: 'text',
processData: false, // bu要去处理发送的数据
contentType: false, //不要去设置Content-Type请求头
success: function(res) {
url = res.data
}
})
}
//后端需要base64,就需要对获取到的数据进行处理
uploadImg (file) {
let reader = new FileReader()
reader.readAsDataURL(file.file)
reader.onload =()=>{
let dataURL = reader.result // 获取到base64编码 包括前缀data:image/jpeg;base64,
}
//此时可以使用最上面直接上传base64的方式进行上传了
}
3.最后一种是最坑的一种,由于图片数据是硬件获取到的,或者是通过摄像头拍照拿到的数据,一般都是base64数据,恰好后端又不支持前端直接上传图片,此时就需要前端对base数据处理,转化成能直接上传的file,就类似于转化成 new FormData()
let bytes = window.atob(base64)
let ab = new ArrayBuffer(bytes.length)
let ia = new Uint8Array(ab)
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
}
let imgs = new File([ab], name, { type: 'image/jpg' })
const formData = new FormData()
formData.append('file', imgs)
//上传操作 下面是前面几篇文章中讲的axios封装的方法,并无不同
const data =await upload(formData)
console.log(data)
//此处上传无论是直接使用ajax还是axios上传都一样,直接把formData放到data那里就行,不需要键值对形势
//ajax上传就类似于第二步中的 $.ajax上传,formData就是file,直接使用即可
最后第三种需要注意点,let imgs = new File([ab], name, { type: 'image/jpg' }) 中的name指的是你自己定义图片的名称,然后生成的formData就包含name以及自己定义的type:'image/jpg' ,一般直接form表单上传name是包含后缀名的,例如图片.jpg等,后端可能会根据后缀去定义图片格式,前端上传命名时候需要注意点,可以自己随意添加后缀名或者直接让后端从type中去取,或者是让后端自己随便定义即可
补充直接上传二进制文件
let fileData = file.file; // 拿到file后,转为FormData格式,这样再发送给后端就可以了
let formData = new FormData();
formData.append("img", fileData);
api_upload(formData) // 发起请求
.then((res)=>{
console.log(res)
})
.catch((err)=>{
console.log(err)
})
//此处直接上传file.file 为二进制文件,不需要将数据转成字符串或其他