上传背景介绍

在项目需求中,关于图片、视频、文件等上传文件,一般不是直接放置在自己的后台服务器上,一般都会购买云服务进行存储。譬如阿里云的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的门,不然,阿里云怎么你有没有给他交钱呢?服务端签名,就是把这个生成钥匙的过程放到了自己后台服务上,让他们去把钥匙给我们。我们前端自己不保管这么敏感的资料。

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

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

// fileUpload.js
import { v4 as uuidv4 } from 'uuid'
import axios from 'axios'
let basePath  = 'www.yourapi.com' // 你的服务器接口域名
/*** @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-shanghai.aliyuncs.com/scrm/1000/test/450821d6-13e1-464e-bc32-569fd277be2c.jpg' }] //图片列表}
},
methods: {// 监听图片上传onSuccessImgFiles(files) {console.log('onSuccessImgFiles', files)this.fileImgList = files}
}

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

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

具体可以看这里:https://help.aliyun.com/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  = 'www.yourapi.com' // 你的服务器接口域名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方法可以参考:
https://www.npmjs.com/package/ali-oss

当然,也可以参考阿里云oss上传的官方文档:
https://help.aliyun.com/document_detail/383952.html

vue项目中上传文件到阿里云oss方法相关推荐

  1. koa中上传文件到阿里云oss实现点击在线预览和下载

    比较好的在线预览的方法: 跳转一个新的页面,里面放一个iframe标签,或者object标签 <iframesrc="xxx"></iframe> < ...

  2. 微信小程序直接上传文件到阿里云OSS组件封装

    微信小程序直接上传文件到OSS 1. 封装公共方法 在根目录utils目录新建一个upload文件夹: // utils/upload/base64.jsvar base64EncodeChars = ...

  3. java上传文件至阿里云oss工具类

    第一步:引入oss maven坐标 <dependency><groupId>com.aliyun.oss</groupId><artifactId>a ...

  4. vue 上传文件至阿里云oss

    先让后端在阿里云里面处理跨域问题 参考这篇文章   vue直传图片到阿里云OSS(单张直接上传)__小郑有点困了的博客-CSDN博客_vue 阿里云背景:近期项目使用到多图片上传功能,常规的调用后端接 ...

  5. go walk 开发window界面,上传文件到阿里云oss -- 服务器端

    前面我们完成了一个网页端的上传oss程序:https://blog.csdn.net/daily886/article/details/103366145 现在我们把前后端分离 前端使用walk开发, ...

  6. go 使用 gin 上传文件到 阿里云oss存储

    本文使用 go 版本是: go version go1.13 linux/amd64 阿里云oss go sdk版本:v2.0.4  官网可以下载 linux版本是:Linux version 3.1 ...

  7. 上传文件到阿里云OSS

    最近项目中有文件上传的功能,才发现阿里云oss真是个好东西. 在其中做了好多的权限设置,角色.子账户.bucket等等. web端进行文件上传有多种方式 一.无需临时授权(安全性较低) (一).拿到权 ...

  8. 【微信小程序】上传文件到阿里云OSS

    小程序上传文件到OSS也是利用OSS提供的PostObject接口来实现表单文件上传到OSS 步骤1:配置Bucket跨域访问 客户端进行表单直传到OSS时,会从浏览器向OSS发送带有Origin的请 ...

  9. Erlang上传文件至阿里云OSS

    忙了快一个月忘记写博客这茬了,正好今天阿里云工作人员又给我打电话我才想起我还买过一个OSS资源包,今天写一个如何调用Erlang代码来将文件资源上传至OSS对象存储中. 前言 OSS对象存储的服务不必 ...

最新文章

  1. java opencv 环境_基于java的OpenCV环境搭建
  2. 在Ubuntu 14.04 64bit上安装批量图片处理器XnConvert
  3. LINUX文件、目录权限及相关操作命令
  4. centos6.9安装Tomcat8.0.36
  5. Matplotlib实例教程(七)密度图
  6. 窗口分析函数_17_计算百分位数
  7. mysql fetch lengths_php mysqli_fetch_lengths()函数
  8. 经典神经网络 | Faster R-CNN论文解析
  9. 比特币链上活跃度下降,近24小时交易额约为1050.57亿美元
  10. jz2440移植QT5.6【学习笔记】【原创】
  11. 电影院售票系统,电影院订票系统,电影院购票管理系统计算机毕业设计
  12. endnote x7不在word中显示
  13. 如何免费去酒吧看球赛并喝扎啤
  14. 2021年下半年软件设计师下午真题试题(案例分析)及答案
  15. Nodejs报内部错误 TypeError: Cannot read property ‘destroy‘ of undefined的解决方法
  16. 【CVPR2020视频超分辨率】Zooming Slow-Mo: Fast and Accurate One-Stage Space-Time Video Super-Resolution 阅读笔记
  17. php中文ascii码范围,标准ascii码字符集共有几个编码?
  18. 大数据平台资源治理经验总结
  19. 百姓网发帖机,发帖机是什么来的
  20. Android垃圾清理功能的初步

热门文章

  1. 新版飞康CDP、NSS全新功能完全解读
  2. 如何测试微信好友是否删除或者拉黑了自己
  3. cobaltstrike的安装与基础使用
  4. bzoj5334 [Tjoi2018]数学计算(线段树)
  5. 中兴助Zeop测试10Gbps宽带服务
  6. 支付宝(纯)担保交易代码实例及其文档
  7. 强化学习论文分析4---异构网络_强化学习_功率控制《Deep Reinforcement Learning for Multi-Agent....》
  8. 计算机英语联想记忆法单词,贝尔学单词电脑版
  9. 谷歌浏览器无法访问网站
  10. material theme 自定义_Angular Material 主题系统(二)-- 自定义主题