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

  1. User management — > create RAM sub-accounts and automatically generate AccessKeyId and AccessKeySecret;
  2. Policy Management — > Create a custom policy to authorize access to the OSS bucket.
  3. Role management — > Create a role and authorize the policies in Step 2 to the role.
  4. Policy Management — > Create a custom policy that authorizes access to the AssumeRole of STS using the role of Step 3.
  5. User management — > Grant the policy in Step 4 to the subaccount in Step 1.
  6. 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.