阿里云 OSS 上传「formData 方式」

预计阅读时间: 3 分钟

需求简介:

  开发过程中,多多少少会用到图片上传、文件上传等,大多数都会选择第三方云服务提供的相关功能,比如阿里云、腾讯云、七牛云等等云服务提供商提供的文件存储运营商提供的服务。本次介绍使用的主要是阿里云的 OSS 文件直传,阿里云存储文件方式有多种,目前主要就工作中用到的阿里云 oss 文件直传做案例做笔记,以便于帮助有类似需求的同行及自己学习。

注意事项:

  1. 文件分类:主要是方便日后文件的管理,同时也便于查找。
  2. 文件重命名:上传文件有时候会出现重名等问题,有时候会给使用者造成一定的影响,不利用用户区分文件是否上传;统一规则对文件进行命名,目的是为了方便日后文件管理维护等。
  3. 文件大小限制:限制上传文件的大小,主要是减少上传完文件等待的时间,以及带宽的消耗,同时也可以减少云存储的存储空间的占用。
  4. 文件存储归类:依据文件的类型、格式、时间等进行文件的归类,目的在于文件规划合理,存储有序,便于后期的管理和维护。

代码实例:

OSS 配置
OSS 配置参数
1/**
2 * [OSS配置]
3 * @type {Object}
4 */
5const conf = {
6	accessKeyId: "accessKeyId", // OSS上传需要的Id
7	accessKeySecret: "accessKeySecret", // OSS上传需要的Secret
8	ali: "https://xxxxx.oss-cn-beijing.aliyuncs.com", // 阿里云OSS存储对象地址
9	bucket: "xxxxx" // 类型
10};

文件重命名(文件分类)

文件重命名
1/**
2 * [文件重命名]
3 * @param  {String} suffixName [文件后缀名]
4 * @return {String}            [文件相对路径名]
5 */
6const fileRename = suffixName => {
7	// 处理时间戳
8	const moment = new Date();
9	let yyyy = moment.getFullYear(),
10		MM = moment.getMonth() + 1,
11		dd = moment.getDate(),
12		hh = moment.getHours(),
13		mm = moment.getMinutes(),
14		ss = moment.getSeconds();
15	// 补“0”
16	MM = MM <= 9 ? "0" + MM : MM;
17	dd = dd <= 9 ? "0" + dd : dd;
18	// 5位数字的随机数
19	let rm = (Math.random() * 1e5).toFixed(),
20		path = `${yyyy}${MM}/${dd}_${hh}${mm}${ss}_${rm}`;
21	return path + suffixName;
22};
23// 格式:yyyyMM/dd_hhmmss_rm.fileType
上传图片函数(uploadImg)
上传图片
1/**
2 * [上传图片]
3 * @param  {Object} file     [上传文件实例]
4 * @param  {String} filePath [上传文件相对路径]
5 * @return {String}          [上传图片生成的路径地址]
6 */
7const uploadImg = async (file, filePath) => {
8	let path = filePath.toLowerCase(),
9		dotIndex = path.lastIndexOf("."),
10		fileType = path.substring(dotIndex);
11	const typeString = ".jpg.jpeg.png";
12	// 限制类型
13	if (!typeString.includes(fileType)) {
14		Message.error("上传图片类型有误,请重新上传!");
15		return null;
16	}
17	// 限制大小
18	if (file.size >= 1024 * 1024) {
19		this.$message.error("上传的图片大小不能超过 1M,请重新上传!");
20		return null;
21	}
22	// 文件后缀名
23	let suffixName = fileRename(fileType);
24	// FormData
25	const form = new FormData();
26	form.append("key", "picture/" + suffixName);
27	form.append("file", file);
28	form.append("accessKeyId", conf.accessKeyId);
29	form.append("success_action_status", 200);
30
31	try {
32		const res = await axios.post(conf.ali, form);
33		if (res.status == 200) {
34			Message.success("上传成功");
35			return conf.ali + "/picture/" + suffixName;
36		} else {
37			Message.error("上传失败:" + res.status);
38			return null;
39		}
40	} catch (error) {
41		console.log(error);
42		Message.error("图片上传失败");
43		return null;
44	}
45};
实例绑定 vue
文件上传 - 示例绑定
1import Vue from "vue";
2import App from "./App.vue";
3// 文件上传
4import uploadImg from "./assets/js/uploadImg";
5
6Object.defineProperties(Vue.prototype, {
7	$oss: { value: uploadImg }
8});
9
10new Vue({
11	render: h => h(App)
12}).$mount("#app");

实例使用:

实例使用
1<template>
2	<el-form :model="user" ref="userForm" :rules="rules" size="small" label-width="80px" class="dialog-form">
3		<el-form-item label="上传图片">
4			<el-row>
5				<el-col :span="8">
6					<el-button type="primary" icon="el-icon-upload" class="uploadBtn" :loading="loading">
7						上传图片
8						<input type="file" accept=".jpg, .jpeg, .png" @change="uploadImg" />
9					</el-button>
10					<p class="up-tip">注:若输入用户头像链接地址同时又上传图片,则上传的图片优先级高于输入的链接地址(建议尺寸200*200)</p>
11				</el-col>
12				<!-- 展示图片 -->
13				<el-col :span="15" :offset="1">
14					<el-image :src="avatar" draggable="false" style="width:144px;height:144px;">
15						<div slot="error" class="image-slot">
16							<i class="el-icon-picture-outline"></i>
17						</div>
18					</el-image>
19				</el-col>
20			</el-row>
21		</el-form-item>
22	</el-form>
23</template>
24
25<script>
26	export default {
27		name: "UploadImg",
28		data() {
29			return {
30				loading: false,
31				avatar: ""
32			};
33		},
34		methods: {
35			// 上传图片
36			uploadImg(e) {
37				// 加载指示器
38				this.loading = true;
39				// file实例
40				let file = e.target.files[0];
41				// file相对路径
42				let filePath = e.target.value;
43				// 文件上传
44				this.$oss(file, filePath).then(url => {
45					this.loading = false;
46					!!url && (this.avatar = url);
47				});
48			}
49		}
50	};
51</script>
注意事项:

图片上传主要 按钮 <input type="file" accept=".jpg, .jpeg, .png" @change="uploadImg" /> ,其中 accept 作用主要是过滤指定类型文件,默认为空「""」(即不做任何限制)。