步骤一:阿里OSS配置
登录阿里云
homenew.console.aliyun.com/home/scene/…
阿里云配置STS AssumeRole临时授权访问OSS资源
- 用户管理——>创建RAM子账号,并自动生成AccessKeyId和AccessKeySecret;
- 策略管理——>新建自定义策略,授权访问OSS的bucket;
- 角色管理——>创建角色,将步骤2的策略授权给该角色;
- 策略管理——>新建自定义策略,授权访问STS的AssumeRole,该策略使用步骤3的角色;
- 用户管理——>将步骤4的策略授权给步骤1 的子账号。
- 使用子账号的AccessKeyId、AccessKeySecret和角色的roleArn,roleSessionName可以自己随意起,申请STS临时授权访问OSS。
步骤二:后端nest配置
ossUpload.service.ts
import { Injectable } from '@nestjs/common';
import config from '../../../config';
import * as STS from '@alicloud/sts-sdk';
@Injectable()
export class OssUploadService {
/**
* 获取 STS 认证
* @param username 登录用户名
*/
async getIdentityFromSTS(username: string) {
const sts = new STS({
endpoint: 'sts.aliyuncs.com',
...config,
});
const identity = await sts.getCallerIdentity();
// 打*号是因为涉及安全问题,具体角色需要询问公司管理阿里云的同事
const stsToken = await sts.assumeRole(`acs:ram::${identity.AccountId}:role/ram***oss`, `${username}`);
return {
code: 200,
data: {
stsToken,
},
msg: 'Success',
};
}
}
ossUpload.module.ts
import { Module } from '@nestjs/common';
import { OssUploadService } from './ossUpload.service';
@Module({
providers: [OssUploadService],
exports: [OssUploadService],
})
export class OssUploadModule {}
ossUpload.controller.ts
import { Controller, Body, Post, Request, UseGuards } from '@nestjs/common';
import { OssUploadService } from './ossUpload.service';
@Controller()
export class OssUploadController {
constructor(private readonly ossUploadService: OssUploadService) {}
@Post('oss-upload')
async getIdentityFromSTS(@Body() Body: any) {
return await this.ossUploadService.getIdentityFromSTS(Body.username);
}
}
报错修复指南链接
help.aliyun.com/knowledge_d…
help.aliyun.com/document_de…
help.aliyun.com/knowledge_d…
步骤三:前端代码
OSSFileUpload.vue
<script lang="ts">
import { Component, Vue, Prop, Emit } from 'vue-property-decorator';
import { getTokenFormLocal } from '@/utils/Storage';
import { API_FILE_UPLOAD } from '@/api';
import oss from '@/utils/ossForUpload.ts';
/**
* 文件上传(aliOSS)
*
* @param {string} action - 上传的地址
* @param {object} data - 上传时附带的额外参数
* @param {string} name - 上传的文件字段名
* @param {object} headers - 设置上传的请求头部
* @param {number} maxSize - 文件上传的大小上限 单位kb
* @param {number} limit - 最大允许上传个数
* @param {string} fileTypes - 上传文件的类型
* @param {array} fileList - 上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
*
* @event on-success - 文件上传成功时的钩子 function(response, file, fileList)
* @event on-remove - 文件列表移除文件时的钩子 function(file, fileList)
* @event on-error - 文件上传错误 function(errorType, file) errorType: typeError 类型不匹配;overSize: 超出大小上线; exceed: 超出最大个数
*/
@Component
export default class OSSFileUpload extends Vue {
@Prop({default() { return []; }}) public fileList!: any[]; // 上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
@Prop({default() {
return `${process.env.VUE_APP_BASE_API_URL}${API_FILE_UPLOAD}`; // 上传接口
}}) public action!: string; // 必选参数,上传的地址
@Prop({default() {
return {};
}}) public data!: object; // 上传时附带的额外参数
@Prop() public name!: string; // 上传的文件字段名
@Prop({
default() {
return {
identity: getTokenFormLocal() || '',
};
},
}) public headers!: object; // 设置上传的请求头部
@Prop(Number) public limit!: number; // 最大允许上传个数
@Prop({default: 5 * 1024}) public maxSize!: number; // 文件上传的大小上线 单位kb
@Prop() public fileTypes!: string;
public httpRequest = oss;
public alertMessage = ''; // 错误信息
@Emit()
public onSuccess(response: any, file: any, fileList: any) {
}
public beforeUpload(file: any) {
file.percentage = 20;
const enabledSize = file.size / 1024;
if (enabledSize > this.maxSize) {
this.$nextTick(function() {
this.alertMessage = `文件大小不得超过${this.maxSize}kb`;
});
this.$emit('on-error-text', 'overSize', file);
return false;
}
this.alertMessage = '';
}
/**
* 文件超出个数限制时的钩子
*/
public onExceed(files: any, fileList: any) {
this.alertMessage = `超出最大上传数量${this.limit}`;
this.$emit('on-error', this.alertMessage, files, fileList);
}
/**
* 文件列表移除文件时的钩子
*/
@Emit()
public onRemove(file: any, fileList: any) {
this.alertMessage = '';
}
public onError(err: any, file: any, fileList: any) {
console.log('报错了');
this.alertMessage = process.env.NODE_ENV === 'production' ? '网络异常,请稍后再试' : err;
this.$emit('on-error', this.alertMessage, err, file, fileList);
}
public uploadProcess(event: any, file: any, fileList: any) {
// console.log('文件上传中');
}
}
</script>
<template>
<section>
<el-alert
:style="{
marginBottom: '8px'
}"
v-show="!!alertMessage"
:
type="error"
show-icon>
</el-alert>
<el-upload
:limit="limit"
:action="action"
:data="data"
:name="name"
:accept="fileTypes"
drag
multiple
:file-list="fileList"
:headers="headers"
:on-success="onSuccess"
:before-upload="beforeUpload"
:on-progress="uploadProcess"
:on-exceed="onExceed"
:on-remove="onRemove"
:http-request="httpRequest"
:on-error="onError">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip"><slot name="tip"></slot></div>
</el-upload>
</section>
</template>
<style lang="less">
</style>
ossForUpload.ts
// 记得npm i ali-oss一下
import * as OSS from 'ali-oss';
import { getPcBasicOss } from '@/model';
import ImgZipper from 'imgzipper';
function getError(action: any, option: any, xhr: any) {
let msg;
if (xhr.response) {
msg = `${xhr.response.error || xhr.response}`;
} else if (xhr.responseText) {
msg = `${xhr.responseText}`;
} else {
msg = `fail to post ${action} ${xhr.status}`;
}
const err: any = new Error(msg);
err.status = xhr.status;
err.method = 'post';
err.url = action;
return err;
}
function getBody(xhr: any) {
const text = xhr.responseText || xhr.response;
if (!text) {
return text;
}
try {
return JSON.parse(text);
} catch (e) {
return text;
}
}
function zipImg(file: any) {
try {
const imageType = file.type.includes('image');
if ( imageType ) {
return new Promise((res, rej) => {
ImgZipper( file, (a: any, b: any) => {
const zipfile = new File([a], file.name, {type: file.type, lastModified: Date.now()});
res(zipfile);
}, {
scale: 0.78, // 生成图像缩放大小
quality: 0.62, // 生成图像的质量
disableBlob: null, // canvas.toBlob方法失败后调用函数
type: 'image/jpeg', // 生成图像格式
exif: true, // 是否使用调整相机旋转
});
});
}
} catch (err) {
throw err;
}
}
export default async function upload(option: any) {
const {file = {}} = option;
const newFile: any = await zipImg(file);
try {
// 这里改成我们node的请求
const { credentials = {} } = await getPcBasicOss({ bucket: 'asal' });
const client = new OSS({
region: credentials.region,
accessKeyId: credentials.AccessKeyId,
accessKeySecret: credentials.AccessKeySecret ,
stsToken: credentials.SecurityToken,
bucket: 你的bucket,
});
const result = await client.put(`/l-web-pc/${newFile.name}`, newFile);
return result;
} catch (err) {
option.onError(err);
throw err;
}
}
PS.如果是后端出接口,那就忽略node配置
如果这篇文章有用,欢迎评论, 点赞, 加关注
。
我是leo:祝大家早日升职加薪。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!