1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > vue项目中上传文件到阿里云oss方法

vue项目中上传文件到阿里云oss方法

时间:2019-03-02 18:02:50

相关推荐

vue项目中上传文件到阿里云oss方法

上传背景介绍

在项目需求中,关于图片、视频、文件等上传文件,一般不是直接放置在自己的后台服务器上,一般都会购买云服务进行存储。譬如阿里云的oss对象存储。

那么,前端开发项目中,涉及到上传的功能时,我们不是把文件上传到自己的后台服务器,而是阿里云上面去,然后拿到文件的访问地址,例如图片的地址,再传递给后台保存下来,保存的是一个阿里云存储地址。

那么,前端如何实现阿里云oss文件上传功能呢?

官方文档上说了:(阿里云oss文档地址)

1、使用阿里云上传的SDK来上传到阿里云oss

2、不使用sdk的方式,直接使用post表单提交到阿里云oss去

3、小程序(忽略)

其实,也就两种。要么使用阿里云给的sdk,他封装的上传方法等;要么使用表单提交,像提交到我们自己服务器一样。

上传方式1:表单直传

Web端通过表单上传方式直接上传数据到OSS。

官方说有如下三种实现方式。

1、在客户端通过JavaScript代码完成签名,然后通过表单直传数据到OSS。详情请参见JavaScript客户端签名直传。2、在服务端完成签名,然后通过表单直传数据到OSS。详情请参见服务端签名后直传。3、在服务端完成签名,并且服务端设置了上传后回调,然后通过表单直传数据到OSS。OSS回调完成后,再将应用服务器响应结果返回给客户端。详情请参见服务端签名直传并设置上传回调。

我司采用的是第2中,服务端签名后,前端在直传oss。

可以理解为:上传前,需要通过阿里云给的账号生成钥匙,然后前端拿到钥匙后去开阿里云oss的门,不然,阿里云怎么你有没有给他交钱呢?服务端签名,就是把这个生成钥匙的过程放到了自己后台服务上,让他们去把钥匙给我们。我们前端自己不保管这么敏感的资料。

具体可以看这里/document_detail/31926.htm?spm=a2c4g.11186623.0.0.3627344eM9Gwj8#concept-en4-sjy-5db

封装的上传示例代码如下:

// fileUpload.jsimport {v4 as uuidv4 } from 'uuid'import axios from 'axios'let basePath = '' // 你的服务器接口域名/*** @description: 文件附件上传* file: 文件raw对象* successCallback: 成功的回调函数* errCallBack: 错误的回调函数* progressCallback: 上传进度的回调函数* dir: 上传阿里云目标文件夹 eg:图片image,视频video等*/const upload = function(file, successCallback = new Function(), errCallBack = new Function(), progressCallback = new Function(), dir = 'image') {let fileName = file.nameaxios({method: 'get',url: basePath + '/aliyun/get', // 请求签名接口,找后台要params: {dir: dir // 'image' // 这里的参数,对应的就是上传到那个文件夹下面,找后台要}}).then(res => {// 拿到签名信息后,组装表单数据,作参考,具体的字段找后台要let obj = res.data.datalet config = {}config.host = obj['host']config.policyBase64 = obj['policy']config.accessid = obj['accessId']config.signature = obj['signature']config.expire = parseInt(obj['expire'])config.callbackbody = obj['callback']config.dir = obj['dir']let fd = new FormData(),uuid = uuidv4(),key = config.dir + uuidfd.append('key', key)fd.append('success_action_status', '200')fd.append('x-oss-object-acl', 'public-read')fd.append('x-oss-meta-fullname', fileName)fd.append('OSSAccessKeyId', config.accessid)fd.append('policy', config.policyBase64)fd.append('signature', config.signature)fd.append('success_action_status', '200')fd.append('file', file)if (config.host.indexOf('http:') > -1) {var protocol = window.location.protocol || 'http:'var subUrl = config.host.substring(5, config.host.length)config.host = protocol + subUrl}// 数据组装完成后,发送上传请求到阿里云ossaxios({url: config.host,method: 'POST',data: fd,processData: false,cache: false,contentType: false,// 这里,我们可以做上传经度onUploadProgress: function(progressEvent) {if (progressEvent.lengthComputable) {let percent = (progressEvent.loaded / progressEvent.total) * 100 || 0progressCallback({percent: percent})}}}).then(() => {// 拿到结果后,做其他操作let size = file.size > 1000000 ? parseFloat(file.size / 1000000).toFixed(2) + 'M' : parseFloat(file.size / 1000).toFixed(2) + 'KB'successCallback({attachment: fileName,aliyunAddress: key,size: size,host: config.host})}).catch(err => {errCallBack(err)})}).catch(err => {errCallBack(err)})}export default upload

那么,在element-ui upload组件中使用自定义上传功能:

<template><div class="text-msg-pic-upload"><el-upload:class="{ display: uploadDisabled }"list-type="picture-card"ref="upload"actionmultiple:http-request="handleUpload":auto-upload="autoUpload":limit="limit":file-list="tempFileList":on-exceed="handleExceed":on-success="handleSuccess":on-remove="handleRemove":before-remove="beforeRemove":before-upload="beforeUpload":on-preview="handlePictureCardPreview"accept="jpg,.jpeg,.png,.JPG,.JPEG"><i class="el-icon-plus"></i><div slot="tip" class="el-upload__tip" v-if="tipsFlag">{{tips }}</div></el-upload><el-dialog :visible.sync="dialogVisible" append-to-body><img width="100%" :src="dialogImageUrl" alt="" /></el-dialog><div class="Upload_pictures"><ul class="el-upload__tip cBBBDBF" style="color: #BBBDBF;"><li>支持PNG、JEPG格式 ,不超过2MB。</li></ul></div></div></template><script>import upload from '@/utils/fileUpload.js'export default {name: 'UploadImageDemo',props: {width: {type: String,default: '240px'},autoUpload: {type: Boolean,default: true},limit: {type: Number,default: 3},limitType: {type: Array,default: () => ['image/jpeg', 'image/png', 'image/jpg']},disabled: {type: Boolean,default: false},imgList: {type: Array,default: () => []},tipsFlag: {type: Boolean,default: false},tips: {type: String,default: ''}},data() {return {// 上传文件列表,el-upload使用,临时保存数据。tempFileList: this.imgList,host: '', // 阿里云上传服务器地址根路径uploadDisabled: false,dialogImageUrl: '',dialogVisible: false}},watch: {// 解决第二渲染接口, 图片还保留着原来的问题 JerryYiimgList: {immediate: true,handler(val) {this.tempFileList = val}}},computed: {upText() {return this.autoUpload ? '上传文件' : '选择文件'}},created() {},mounted() {},methods: {handlePictureCardPreview(file) {this.dialogImageUrl = file.urlthis.dialogVisible = true},beforeUpload(file) {// console.log('beforeUpload', file)let types = this.limitTypeconst isImage = types.includes(file.type)const isLt20M = file.size / 1024 / 1024 < 10if (!isImage) {this.$message({message: types.length == 0 ? '上传图片只能是 PNG 格式!' : '上传图片只能是 JPG、PNG 格式!',type: 'warning'})return false}if (!isLt20M) {this.$message.error('上传图片大小不能超过 1MB!')return false}return isImage && isLt20M},// 自定义上传操作handleUpload(op) {let dir = `images`upload(op.file,res => {let temp = {name: res.attachment,url: res.host + '/' + res.aliyunAddress}this.host = res.hostop.onSuccess(temp)},err => {console.log(err)},res => {op.onProgress(res)},dir)},// 上传成功后触发handleSuccess(response, file, fileList) {this.filterFileFn(fileList)},// 返回给接口要用的格式filterFileFn(fileList) {let filterArr = fileList.filter(item => !item.status || item.status !== 'ready') // 过滤未上传的文件.map(item => {let url = item.response ? item.response.url : item.urlreturn {url: url, // item.url || item.response.urlname: item.name}})// console.log('fileList', fileList)this.$emit('onSuccessFiles', filterArr)},// 监听移除文件列表handleRemove(file, fileList) {if (file.status === 'success') {this.filterFileFn(fileList)}},handleExceed(files, fileList) {this.$message({message: `当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`, type: 'warning' })},beforeRemove() {// return this.$confirm(`确定移除 ${file.name}?`)}}}</script><style>.text-msg-pic-upload .el-upload--picture-card,.text-msg-pic-upload .el-upload-list--picture-card .el-upload-list__item {width: 62px;height: 62px;line-height: 72px;}.display .el-upload--picture-card {display: none;}</style>

使用:

<UploadImage :limit="9" :imgList="fileImgList" @onSuccessFiles="onSuccessImgFiles" />// ...........其他略data(){return{fileImgList: [{name: 'test', url: 'http://testworldunion.oss-cn-/scrm/1000/test/450821d6-13e1-464e-bc32-569fd277be2c.jpg' }] //图片列表}},methods: {// 监听图片上传onSuccessImgFiles(files) {console.log('onSuccessImgFiles', files)this.fileImgList = files}}

一句话: 使用el-upload的自定义上传,结合我们封装的函数,实现上传功能。

上传方式二:阿里云oss SDK上传

具体可以看这里:/document_detail/64047.htm?spm=a2c4g.11186623.0.0.119f3967Xq1Eb8#concept-64047-zh

这种方式,需要安装依赖包或引入js文件。

npm install ali-oss

同样的,我们封装一下上传:

import {v4 as uuidv4 } from 'uuid'import axios from 'axios'let basePath = '' // 你的服务器接口域名const OSS = require('ali-oss')/*** 阿里云oss sdk文件上传* @param {*} file 文件流* @param {*} successCallback 成功回调* @param {*} errCallBack 失败回调* @param {*} bucketName 阿里云桶名(可以指定多个桶名)* @param {*} dir 上传文件夹路径 譬如images*/export function bucketUpload(file, successCallback = new Function(), errCallBack = new Function(), bucketName = '你的阿里云桶名', dir = 'image') {let fileName = file.namelet pathName = window.location.hostlet bucketNameTemp = bucketNamelet requestData = {bucket: bucketNameTemp,dir: dir}// 先获取上传要的资料签名axios({method: 'post',url: basePath + '/aliyunsts', // 找后台要接口,返回new OSS需要的参数headers: {'Content-Type': 'application/json'},data: requestData // 这里的参数,看后台要什么,沟通确定}).then(res => {let obj = res.data || {}let config = {}// console.log(obj)config.host = obj.OssUrl// 实例化一个上传客户端const client = new OSS({// yourRegion填写Bucket所在地域。Region填写为oss-cn-hangzhou。region: obj.OssRegion,// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。accessKeyId: obj.AccessKeyId,accessKeySecret: obj.AccessKeySecret,// 从STS服务获取的安全令牌(SecurityToken)。stsToken: obj.SecurityToken,// 填写Bucket名称。bucket: obj.BucketName})try {// 填写Object完整路径。Object完整路径中不能包含Bucket名称。// 您可以通过自定义文件名(例如exampleobject.txt)或文件完整路径(例如exampledir/exampleobject.txt)的形式实现将数据上传到当前Bucket或Bucket中的指定目录。// data对象可以自定义为file对象、Blob数据或者OSS Buffer。// 为保证唯一性,通过uuid将文件名替换let uuid = uuidv4() + fileName.substring(fileName.lastIndexOf('.'))if (dir.substring(dir.length - 1, 1) !== '/') {dir += '/'}const result = client.put(dir + uuid, file)result.then(res => {console.log(res)let size = file.size > 1000000 ? parseFloat(file.size / 1000000).toFixed(2) + 'M' : parseFloat(file.size / 1000).toFixed(2) + 'KB'successCallback({attachment: fileName,aliyunAddress: res.url,size: size,host: config.host})}).catch(err => {errCallBack(err)})} catch (e) {console.log(e)}}).catch(err => {errCallBack(err)})}

对应的el-upload中的自定义上传方法就改了:

handleUpload(op) {let bucketName = 'myaliyunossbucketname' // 桶名let dir = `images`bucketUpload(op.file,res => {let temp = {name: res.attachment,url: res.aliyunAddress}this.host = res.hostop.onSuccess(temp)},err => {console.log(err)},bucketName,dir)

这种方式,有点缺陷,就是不能使用上传进度。

如果要使用上传进度,就需要使用分片上传功能才行。

我们简单上传使用的这个put方法。不支持进度功能。

进度功能,需要使用另外一个方法:

所有的api方法可以参考:

/package/ali-oss

当然,也可以参考阿里云oss上传的官方文档:

/document_detail/383952.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。