#OSS 上传「FormData」
#需求简介:
开发过程中,多多少少会用到图片上传、文件上传等,大多数都会选择第三方云服务提供的相关功能,比如阿里云、腾讯云、七牛云等等云服务提供商提供的文件存储运营商提供的服务。本次介绍使用的主要是阿里云的 OSS 文件直传,阿里云存储文件方式有多种,目前主要就工作中用到的阿里云 oss 文件直传做案例做笔记,以便于帮助有类似需求的同行及自己学习。
#注意事项:
- 文件分类:主要是方便日后文件的管理,同时也便于查找。
- 文件重命名:上传文件有时候会出现重名等问题,有时候会给使用者造成一定的影响,不利用用户区分文件是否上传;统一规则对文件进行命名,目的是为了方便日后文件管理维护等。
- 文件大小限制:限制上传文件的大小,主要是减少上传完文件等待的时间,以及带宽的消耗,同时也可以减少云存储的存储空间的占用。
- 文件存储归类:依据文件的类型、格式、时间等进行文件的归类,目的在于文件规划合理,存储有序,便于后期的管理和维护。
#代码实例:
#OSS 配置
OSS 配置参数
/**
* [OSS配置]
* @type {Object}
*/
const conf = {
accessKeyId: "accessKeyId", // OSS上传需要的Id
accessKeySecret: "accessKeySecret", // OSS上传需要的Secret
ali: "https://xxxxx.oss-cn-beijing.aliyuncs.com", // 阿里云OSS存储对象地址
bucket: "xxxxx", // 类型
};#文件重命名(文件分类)
文件重命名
/**
* [文件重命名]
* @param {String} suffixName [文件后缀名]
* @return {String} [文件相对路径名]
*/
const fileRename = (suffixName) => {
// 处理时间戳
const moment = new Date();
let yyyy = moment.getFullYear(),
MM = moment.getMonth() + 1,
dd = moment.getDate(),
hh = moment.getHours(),
mm = moment.getMinutes(),
ss = moment.getSeconds();
// 补“0”
MM = MM <= 9 ? "0" + MM : MM;
dd = dd <= 9 ? "0" + dd : dd;
// 5位数字的随机数
let rm = (Math.random() * 1e5).toFixed(),
path = `${yyyy}${MM}/${dd}_${hh}${mm}${ss}_${rm}`;
return path + suffixName;
};
// 格式:yyyyMM/dd_hhmmss_rm.fileType#上传图片函数(uploadImg)
上传图片
/**
* [上传图片]
* @param {Object} file [上传文件实例]
* @param {String} filePath [上传文件相对路径]
* @return {String} [上传图片生成的路径地址]
*/
const uploadImg = async (file, filePath) => {
let path = filePath.toLowerCase(),
dotIndex = path.lastIndexOf("."),
fileType = path.substring(dotIndex);
const typeString = ".jpg.jpeg.png";
// 限制类型
if (!typeString.includes(fileType)) {
Message.error("上传图片类型有误,请重新上传!");
return null;
}
// 限制大小
if (file.size >= 1024 * 1024) {
this.$message.error("上传的图片大小不能超过 1M,请重新上传!");
return null;
}
// 文件后缀名
let suffixName = fileRename(fileType);
// FormData
const form = new FormData();
form.append("key", "picture/" + suffixName);
form.append("file", file);
form.append("accessKeyId", conf.accessKeyId);
form.append("success_action_status", 200);
try {
const res = await axios.post(conf.ali, form);
if (res.status == 200) {
Message.success("上传成功");
return conf.ali + "/picture/" + suffixName;
} else {
Message.error("上传失败:" + res.status);
return null;
}
} catch (error) {
console.log(error);
Message.error("图片上传失败");
return null;
}
};#实例绑定 vue
文件上传 - 示例绑定
import Vue from "vue";
import App from "./App.vue";
// 文件上传
import uploadImg from "./assets/js/uploadImg";
Object.defineProperties(Vue.prototype, {
$oss: { value: uploadImg },
});
new Vue({
render: (h) => h(App),
}).$mount("#app");#实例使用:
实例使用
<template>
<el-form
:model="user"
ref="userForm"
:rules="rules"
size="small"
label-width="80px"
class="dialog-form"
>
<el-form-item label="上传图片">
<el-row>
<el-col :span="8">
<el-button
type="primary"
icon="el-icon-upload"
class="uploadBtn"
:loading="loading"
>
上传图片
<input
type="file"
accept=".jpg, .jpeg, .png"
@change="uploadImg"
/>
</el-button>
<p class="up-tip">
注:若输入用户头像链接地址同时又上传图片,则上传的图片优先级高于输入的链接地址(建议尺寸200*200)
</p>
</el-col>
<!-- 展示图片 -->
<el-col :span="15" :offset="1">
<el-image
:src="avatar"
draggable="false"
style="width:144px;height:144px;"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</el-col>
</el-row>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: "UploadImg",
data() {
return {
loading: false,
avatar: "",
};
},
methods: {
// 上传图片
uploadImg(e) {
// 加载指示器
this.loading = true;
// file实例
let file = e.target.files[0];
// file相对路径
let filePath = e.target.value;
// 文件上传
this.$oss(file, filePath).then((url) => {
this.loading = false;
!!url && (this.avatar = url);
});
},
},
};
</script>注意事项
图片上传主要 按钮 <input type="file" accept=".jpg, .jpeg, .png" @change="uploadImg" /> ,其中 accept 作用主要是过滤指定类型文件,默认为空「""」(即不做任何限制)。