最近项目需求,做一个图片上传到阿里云oss的功能,由于之前没做过这样的功能,所以也是查阅了不少资料,边写demo边测试把基本功能完成了。现在来记录下,没做过的童鞋也可以简单参考下。我的使用场景是在vue项目中结合iview框架的上传组件来实现功能。
首先给大家一篇阿里云的文档 web端直传实践,它里面给出了三个上传的例子,如下图:
最开始我们后端让我自己看看这些例子,也没决定好用哪种方式,而我选择尝试的是第一种方式,因为不需要后端直接参与。那我就先从第一种方式开始说起,在这之前你需要开通好阿里云的对象存储功能,并新建了一个Bucket
,这些我就直接略过了,给个文档:使用阿里云OSS
JavaScript客户端签名直传
这种方式不需要后端直接参与,你只需要配置好阿里云oss的后台就好,非常方便。但是客户端通过JavaScript把AccesssKeyID和AccessKeySecret写在代码里面有泄露的风险。关于AccesssKeyID和AccessKeySecret,参考上面给的文档里的介绍。
每种方式官方都给出了demo代码,你可以下载下来参考一下,不过我觉得例子代码有点多,就没用他那种方式。阿里云提供了一个sdk可以帮助我们来实现文件上传。这里是SDK参考
我是直接使用它的cdn引入的,在index.html中直接引入:1
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script>
之前说了我是结合iview框架的上传组件的,我把上传功能单独写成了一个组件,为防止大家看的难受,这里只贴上部分核心代码:
template:1
2
3
4
5
6
7
8
9
10
11
12
13// iview上传组件
<Upload
:before-upload="handleBeforUpload" // before-upload 上传文件之前的钩子,参数为上传的文件
action=""
>
<Button icon="ios-cloud-upload-outline">选择文件</Button>
</Upload>
// 显示选择的图片名
<div v-if="file">已选择文件:{{file.name}}
// 手动点击上传
<Button @click="upLoad">点击上传</Button>
script:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35data(){
return {
file:'' // 选择上传的文件
}
},
methods:{
// 上传之前的操作
handleBeforUpload (file) {
this.file = file // 将回调的文件信息存入data.file
return false // 返回false,表示手动上传,取消默认的自动上传
},
// 点击上传按钮触发上传操作
upload(){
// sdk提供的创建客户端实例方法
const client = new OSS.Wrapper({
region: 'oss-cn-hangzhou', // 创建Bucket时会选择不同地区,根据自己的选择填入对应名称
accessKeyId: '********', // 填入你的accessKeyId
accessKeySecret: '********', // 填入你的accessKeySecret
bucket: '***' // 填入你的bucket名
})
const Name = this.file.name
const suffix = Name.substr(Name.indexOf('.')) // 文件后缀
const filename = Date.parse(new Date()) + suffix // 组成新文件名
client.multipartUpload(filename, this.file).then(res => { // 上传
console.log('上传成功:',res)
// ... 你的操作,可以拼接图片url,用于显示等...
}).catch(err => {
console.log('上传失败:', err)
})
}
}
以上就是一个最简单的上传图片功能,总结就是:取消iview组件默认的自动上传功能,选择手动上传,在上传之前拿到图片信息,在点击上传按钮时,借助sdk提供的方法,填入你的OSS参数,最后将图片上传。上传成功之后,可以到OSS管理控制台的文件管理中看到图片信息。
服务端签名直传并设置上传回调
我和后端最终选择的方式就是这种,至于为啥,显然上面那种方法看起来不那么安全,更多的区别还是去看文档介绍的。
同样的,这种方法也提供了demo,但是我依旧没用它的方式去实现我的功能。我还是先贴上少部分核心的代码,其中上面的template部分不用变,主要来看看js部分的实现:
首先handleBeforUpload
中,我们需要加一步获取参数的方法,并组成要上传的数据1
2
3
4
5
6
7
8handleBeforUpload (file) {
this.file = file
// 获取上传文件前服务器给的参数
this.$store.dispatch('handleGetAllOss').then(res => {
this.setParams(res.data) // 组装我们要上传的数据,方法的代码在下面
})
return false
},
我使用了vuex,所以请求都写在了actions里,handleGetAllOss
这个action里会请求一些上传需要的参数,请求地址是需要后端提供的,所以如果用这种方式的话,后端大佬的大腿要抱牢。关于请求我就不多说了,就简单发个ajax的get请求拿到参数就好。想要知道会有哪些参数,我们重点来看setParams
这个方法:
1 | setParams (data) { |
现在我们有了要上传的数据this.formData
,有了上传地址:this.url
,现在只要使用ajax的post请求就好了,当点击上传按钮时,调用upload
方法:1
2
3
4
5
6
7
8upload(){
this.$store.dispatch('handleUploadImg', { url: this.url, data: this.formData }).then(res => {
console.log('上传成功:',res)
// 你的操作
}).catch(err => {
console.log('上传失败:',err)
})
}
我还是把我的啰嗦的代码贴出来吧
handleUploadImg
方法:1
2
3
4
5
6
7
8
9
10
11
12// 上传
handleUploadImg ({ commit }, { url, data }) {
return new Promise((resolve, reject) => {
uploadImg({ url, data }) // 方法在下面
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
uploadImg
方法:1
2
3
4
5
6
7
8const uploadImg = ({ url, data }) => {
return axios.request({ // axios.request 方法是简单的对axios的封装,看这配置也应该不需要多介绍
url,
data,
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' }
})
}
上面的流程就是这种上传方式的简单实现,你不必按照我的方式来,总结一下就是:
- 请求后端给你的地址,拿到上传时必要的参数
- 将获取的参数拼装至formData
- 使用post方法发送请求,带上formData数据,请求地址在步骤1的参数里,host参数。
- post请求成功后的回调,是后端可控的,我让后端加了一个图片名返回,自己拼接图片url。
这个过程需要后端的参与。
图片处理(缩略图)
本来没这步的,想想还是写上来,觉得阿里云这个功能挺好用的。
通过上面的两种方式可以成功上传图片到阿里云的对象存储,然后就可以使用url访问图片了。一般上传成功后,在页面上会显示一个缩略图,这个缩略图不仅仅是你设置宽高看起来小,实际上它真的可以变小。在阿里云OSS管理控制台,点击图片处理
,点击新建样式
,你会看到下面这样:
如图你可以在右侧添加一个图片样式,比如可以选择缩略比例,设置好后点确定就会生成一个图片样式,我图中已经有一个min_img
名的样式,表示缩略图的意思,这样在我想要访问某个图片的缩略图时,在图片url后面加上?x-oss-process=style/min_img
这个后缀就好了,min_img
替换成你设置的样式名。
结语
本人也是刚接触这个,实现的也是最基本的功能,实现过程也可能并不正确。有做过这个的童鞋们可以多给点意见,谢谢。🙏