Today, the background said that the upload file bandwidth, to find a way to upload the front end, do not go to the background, can not eat. So we have the following exploration.
Step 1: Ali OSS configuration
Log in to Aliyun
Homenew.console.aliyun.com/home/scene/…
Ali Cloud is configured with STS Sumerole temporary authorization to access OSS resources
- User management — > create RAM sub-accounts and automatically generate AccessKeyId and AccessKeySecret;
- Policy Management — > Create a custom policy to authorize access to the OSS bucket.
- Role management — > Create a role and authorize the policies in Step 2 to the role.
- Policy Management — > Create a custom policy that authorizes access to the AssumeRole of STS using the role of Step 3.
- User management — > Grant the policy in Step 4 to the subaccount in Step 1.
- RoleSessionName can apply for STS temporary authorization to access OSS at will, using the AccessKeyId and AccessKeySecret of the child account and the roleArn of the role.
Step 2: Back-end Nest configuration
ossUpload.service.ts
import { Injectable } from '@nestjs/common';
import config from '.. /.. /.. /config';
import * as STS from '@alicloud/sts-sdk';
@Injectable(a)export class OssUploadService {
/** * Obtain STS certification *@param Username login username */
async getIdentityFromSTS(username: string) {
const sts = new STS({
endpoint: 'sts.aliyuncs.com'. config, });const identity = await sts.getCallerIdentity();
// The * number is marked because it involves security issues. The specific role should be asked to the colleague who manages Aliyun
const stsToken = await sts.assumeRole(`acs:ram::${identity.AccountId}:role/ram***oss`.`${username}`);
return {
code: 200.data: {
stsToken,
},
msg: 'Success'}; }}Copy the code
ossUpload.module.ts
import { Module } from '@nestjs/common';
import { OssUploadService } from './ossUpload.service';
@Module({
providers: [OssUploadService],
exports: [OssUploadService],
})
export class OssUploadModule {}
Copy the code
ossUpload.controller.ts
import { Controller, Body, Post, Request, UseGuards } from '@nestjs/common';
import { OssUploadService } from './ossUpload.service';
@Controller(a)export class OssUploadController {
constructor(private readonly ossUploadService: OssUploadService) {}
@Post('oss-upload')
async getIdentityFromSTS(@Body() Body: any) {
return await this.ossUploadService.getIdentityFromSTS(Body.username); }}Copy the code
Error repair guide link
Help.aliyun.com/knowledge_d…
Help.aliyun.com/document_de…
Help.aliyun.com/knowledge_d…
Step 3: Front-end code
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';
/** * File upload (aliOSS) **@param {string} action- Upload address *@param {object} data- Additional parameters attached to upload *@param {string} name- Name of the uploaded file field *@param {object} headers- Set the upload request header *@param {number} maxSize- Maximum size of a file to be uploaded unit: KB *@param {number} limit- Maximum number of uploads *@param {string} fileTypes- Type of the file to be uploaded *@param {array} fileList- upload file list, for example: [{name: 'food. JPG, url: "https://xxx.cdn.com/xxx.jpg"}] * *@event on- SUCCESS - Hook function(Response, file, fileList) * when a file is uploaded successfully@event on-remove - Specifies the hook function(file, fileList) * for removing files from the file list@event on-error - File upload error function(errorType, file) errorType: typeError type mismatch; OverSize: the size exceeds the upper limit. Exceed: exceeds the maximum number */
@Component
export default class OSSFileUpload extends Vue {
@Prop({default() { return []; }}) publicfileList! :any[]; / / upload file list, such as: [{name: 'food. JPG, url: "https://xxx.cdn.com/xxx.jpg"}]
@Prop({default() {
return `${process.env.VUE_APP_BASE_API_URL}${API_FILE_UPLOAD}`; // Upload interface
}}) publicaction! :string; // This parameter is mandatory
@Prop({default() {
return {};
}}) publicdata! :object; // Additional parameters attached to upload
@Prop(a)publicname! :string; // The name of the uploaded file field
@Prop({
default() {
return {
identity: getTokenFormLocal() || ' '}; }})publicheaders! :object; // Set the upload request header
@Prop(Number) publiclimit! :number; // Maximum number of uploads allowed
@Prop({default: 5 * 1024}) publicmaxSize! :number; // The size of the file to be uploaded is in KB
@Prop(a)publicfileTypes! :string;
public httpRequest = oss;
public alertMessage = ' '; // Error message
@Emit(a)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 = File size must not exceedThe ${this.maxSize}kb`;
});
this.$emit('on-error-text'.'overSize', file);
return false;
}
this.alertMessage = ' ';
}
/** * Hook */ when the number of files exceeds the limit
public onExceed(files: any, fileList: any) {
this.alertMessage = 'Exceeded the maximum number of uploadsThe ${this.limit}`;
this.$emit('on-error'.this.alertMessage, files, fileList);
}
/** * File list to remove the file when the hook */
@Emit(a)public onRemove(file: any, fileList: any) {
this.alertMessage = ' ';
}
public onError(err: any, file: any, fileList: any) {
console.log('Error reported');
this.alertMessage = process.env.NODE_ENV === 'production' ? 'Network exception, please try again later' : err;
this.$emit('on-error'.this.alertMessage, err, file, fileList);
}
public uploadProcess(event: any, file: any, fileList: any) {
// console.log(' file is being uploaded ');
}
}
</script>
<template>
<section>
<el-alert
:style="{ marginBottom: '8px' }"
v-show="!!!!! alertMessage"
:title="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">Drag the file here, or<em>Click on the upload</em></div>
<div class="el-upload__tip" slot="tip"><slot name="tip"></slot></div>
</el-upload>
</section>
</template>
<style lang="less">
</style>
Copy the code
ossForUpload.ts
// Remember 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) {
returntext; }}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.// Generate image zoom size
quality: 0.62.// The quality of the generated image
disableBlob: null.// The canvas.toBlob method fails
type: 'image/jpeg'.// Generate the image format
exif: true.// Whether to adjust camera rotation}); }); }}catch (err) {
throwerr; }}export default async function upload(option: any) {
const {file = {}} = option;
const newFile: any = await zipImg(file);
try {
// Change this to our node request
const { credentials = {} } = await getPcBasicOss({ bucket: 'asal' });
const client = new OSS({
region: credentials.region,
accessKeyId: credentials.AccessKeyId,
accessKeySecret: credentials.AccessKeySecret ,
stsToken: credentials.SecurityToken,
bucket: your bucket,});const result = await client.put(`/l-web-pc/${newFile.name}`, newFile);
return result;
} catch (err) {
option.onError(err);
throwerr; }}Copy the code
PS. If it is a back-end outbound interface, ignore the Node configuration
If this article is useful, feel free to comment, like, and follow.
I’m Leo: I wish you all a promotion and a raise soon.