前置条件 Vue3 ali-oss

自行安装依赖 yarn add ali-oss 自己找个文件夹,然后创建 oss.ts 文件accessKeyId: ‘’,accessKeySecret: ‘’, 去oss管理器找

import OSS from 'ali-oss';

import { buildShortUUID } from '/@/utils/uuid';

import { urlToBase64, dataURLtoBlob } from '/@/utils/file/base64Conver';

// @ts-ignore

const isDev = ['development', 'test', 'dev'].includes(process.env.NODE_ENV);

/**

* @description 获取oss实例

* @param region 桶所在区域

* @param bucket 桶名称

*/

export function getOssClient({}: {

region?: 'DEFAULT' /* 桶所在区域 */;

bucket?: 'DEFAULT' /* 桶名称 */;

}) {

return new OSS({

region: 'oss-cn-hangzhou' /* Bucket所在地域 */,

// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。

accessKeyId: '', //oss accessKeyId

accessKeySecret: '', // oss accessKeySecret

// 从STS服务获取的安全令牌(SecurityToken)。

// stsToken: 'yourSecurityToken',

// refreshSTSToken: async () => {

// 向您搭建的STS服务获取临时访问凭证。

// const info = await fetch('your_sts_server');

// return {

// accessKeyId: info.accessKeyId,

// accessKeySecret: info.accessKeySecret,

// stsToken: info.stsToken,

// };

// },

// refreshSTSTokenInterval: 300000/* 刷新临时访问凭证的时间间隔,单位为毫秒 */,

bucket: 'ali-dish' /* Bucket名称 */,

});

}

interface UploadFileResultModule {

name: string;

url: string;

domain: string;

fastDomain: string;

dir: string;

fileName: string;

fastUrl: string;

res: {

status: string;

statusCode: string;

headers: {

'content-length': string;

};

size: string;

aborted: boolean;

rt: string;

keepAliveSocket: boolean;

data: {

type: string;

data: any[];

};

requestUrls: string[];

timing: any;

remoteAddress: string;

remotePort: string;

};

}

/**

* @description 简单上传文件

* @param data 文件

* @param fileName 文件名称

* @param reName 是否重命名

* @param mineType 文件类型,即文件后缀

* @param dir 文件存储路径

* @param region 桶所在区域

* @param bucket 桶名称

*/

export async function uploadFile({

data,

fileName,

reName = true,

mineType,

region = 'DEFAULT',

bucket = 'DEFAULT',

}: {

data: Blob /* 文件 */;

fileName?: string /* 文件名称 */;

reName?: boolean /* 是否重命名 */;

mineType?: string /* 文件类型,即文件后缀 */;

dir?: 'FOOD_MAIN_IMG' /* 文件存储路径 */;

region?: 'DEFAULT' /* 桶所在区域 */;

bucket?: 'DEFAULT' /* 桶名称 */;

}): Promise {

function getFileName(): string {

let name = '';

if (fileName && fileName.indexOf('.') > -1) {

const arr = fileName.split('.');

for (let i = 0; i < arr.length - 1; i++) {

name += arr[i];

}

name =

(reName ? buildShortUUID(name) : arr[arr.length - 2]) +

'.' +

(mineType || arr[arr.length - 1] || 'png');

} else {

name =

(reName ? buildShortUUID(new Date().getTime().toString()) : fileName) +

'.' +

(mineType || 'png');

}

return name;

}

const saveFileName = getFileName();

const fullPath = `${'index/main/'}${saveFileName}`;

const res = await getOssClient({ region, bucket }).put(fullPath, data);

return {

...res,

domain: 'http://XXX.oss-cn-hangzhou.aliyuncs.com',

fastDomain: 'http://XXX.oss-cn-hangzhou.aliyuncs.com',

dir: 'index/main/',

fileName: saveFileName,

fastUrl: 'http://XXX.oss-cn-hangzhou.aliyuncs.com' + '/' + 'index/main/' + saveFileName,

};

}

export async function uploadFileByUrl(

url: string | string[],

{

dir = 'DISH_MAIN_IMG',

fileName,

region = 'DEFAULT',

bucket = isDev ? 'DEFAULT_TEST' : 'DEFAULT',

}: {

fileName?: string /* 文件名称 */;

dir?: 'DISH_MAIN_IMG' /* 文件存储路径 */;

region?: 'DEFAULT' /* 桶所在区域 */;

bucket?: 'DEFAULT' /* 桶名称 */;

}

) {

async function single(item) {

let arr: string[] = [];

let blob;

if (item.indexOf('data:') === 0) {

arr = ['png'];

blob = dataURLtoBlob(item);

} else {

arr = item.split('.');

blob = dataURLtoBlob(await urlToBase64(item));

}

return await uploadFile({

data: blob,

dir,

fileName,

region,

bucket,

mineType: arr[arr.length - 1],

});

}

if (typeof url === 'string') {

return single(url);

} else {

const arr = new Array(url.length).fill(null);

for (let index = 0; index < url.length; index++) {

const item = url[index];

const result = await single(item);

arr[index] = result;

if (arr.indexOf(null) < 0) {

return Promise.resolve(arr);

}

}

}

}

class FfileReader extends FileReader {

file;

proportion /* 图片或视频尺寸比例 */;

maxSize /* 最大文件尺寸,单位kb */;

maxWidth /* 最大文件宽度 */;

maxHeight /* 最大文件高度 */;

imgWidth /* 最大文件宽度 */;

imgHeight /* 最大文件高度 */;

status = 0 /* 文件读取状态 */;

// loaded = null /* 读取完成后的结果 */;

message = '';

ecb = Function;

constructor(

file = File,

proportion = '',

maxSize = 0,

maxWidth = 0,

maxHeight = 0,

imgWidth = 0,

imgHeight = 0,

cb = Function,

ecb = Function

) {

super();

this.file = file;

this.proportion = proportion;

this.maxSize = maxSize;

this.maxWidth = maxWidth;

this.maxHeight = maxHeight;

this.imgWidth = imgWidth;

this.imgHeight = imgHeight;

if (ecb) {

this.ecb = ecb;

}

this.status = super.readyState;

super.onabort = this.err;

super.onerror = this.err;

super.onload = (e) => {

const size = {

width: 0,

height: 0,

};

const load = () => {

if (maxSize && e.total / 1024 > maxSize) {

this.message = `单个文件大小不能超过${maxSize / 1024}m,文件${file.name}大小为:${(

e.total /

1024 /

1024

).toFixed(2)}m`;

} else if (maxWidth && size.width && size.width > maxWidth) {

this.message = `单个文件宽度不能超过${maxWidth}像素,文件${file.name}宽度为:${size.width}像素`;

} else if (maxHeight && size.height > maxHeight) {

this.message = `单个文件高度不能超过${maxHeight}像素,文件${file.name}高度为:${size.height}像素`;

} else if (imgWidth && size.width && size.width != imgWidth) {

this.message = `图片宽度必须为${imgWidth}像素,文件${file.name}宽度为:${size.width}像素`;

} else if (imgHeight && size.height != imgHeight) {

this.message = `图片高度必须为${imgHeight}像素,文件${file.name}高度为:${size.height}像素`;

} else if (proportion && size.width && size.height) {

const arr = proportion.split(/[,.|:~`!@#$%^&*-/_/=+;/\\?><]/);

if (

arr.length == 2 &&

Number(arr[0]) &&

Number(arr[1]) &&

size.width / size.height != Number(arr[0]) / Number(arr[1])

) {

this.message = `单个文件尺寸比例为${arr[0] + ':' + arr[1]}像素,文件${

file.name

}尺寸比例为:${'1:' + (size.height / size.width).toFixed(2)}`;

}

}

if (this.message) {

// Vue.prototype.$message({

// message: this.message,

// type: "error",

// });

ecb && ecb();

super.abort();

} else if (e.target && e.target.result) {

const path = e.target.result;

cb &&

cb({

file,

path,

});

}

};

if (this.file.type.indexOf('image') > -1) {

const imageObj = new Image();

imageObj.src = String(e.target && e.target.result);

imageObj.onload = function () {

size.width = imageObj.width;

size.height = imageObj.height;

load();

};

} else if (this.file.type.indexOf('video') > -1) {

const videoUrl = URL.createObjectURL(file);

const videoObj = document.createElement('video');

videoObj.onloadedmetadata = () => {

URL.revokeObjectURL(videoUrl);

size.width = videoObj.videoWidth;

size.height = videoObj.videoHeight;

load();

};

videoObj.src = videoUrl;

videoObj.load();

} else {

load();

}

};

super.readAsDataURL(this.file);

}

err() {

this.status = -1;

this.ecb && this.ecb();

}

}

//上传文件

export function chooseFile({

cb,

max = 1,

accept = '',

proportion = '',

maxSize = 0,

maxWidth = 0,

maxHeight = 0,

imgWidth = 0,

imgHeight = 0,

loading = '',

}) {

const el = document.createElement('input');

el.setAttribute('type', 'file');

if (max > 1) {

el.setAttribute('multiple', 'true');

}

if (accept) {

el.setAttribute('accept', accept);

}

el.click();

let waiting = false; // 是否尚在等待选择文件

let clicked = false; // 按钮是否被点击

el.addEventListener('click', () => {

clicked = true; // 按钮被点击

waiting = true; // 等待用户选择文件, 此时按钮会失去焦点

});

el.addEventListener('blur', () => {

if (clicked && waiting) {

clicked = false; // 用户点击容器后, 容器会失去一次焦点, 此时处于waiting状态

// waiting没有被input的change事件置为false, 却触发了blur的失焦事件

} else if (waiting) {

// 容器再次失去焦点, 仍旧处于waiting状态, 断言用户取消了选择

console.log('blur事件测试到用户取消了选择');

}

});

el.addEventListener('change', () => {

// if (loading) {

// loading = Vue.prototype.$loading({

// target: loading,

// lock: true,

// text: "加载中...",

// spinner: "el-icon-loading",

// background: "rgba(0, 0, 0, 0.7)",

// });

// }

waiting = false; // 检测到用户选择了文件

let files = el.files || [];

const data = [];

if (files.length) {

const status = [];

if (files.length > max) {

/* 检测到用户选择文件数量超出限制,取前面符合数量的文件 */

console.log(files.length, max);

const fileList = [];

for (let i = 0; i < files.length; i++) {

const element = files[i];

if (i < max) {

fileList.push(element);

}

}

files = fileList;

// Vue.prototype.$message({

// message: `您选择的文件数量超出限制,已取前${max}个文件。`,

// type: "warn",

// });

}

for (const item of files) {

const fr = new FfileReader(

item,

proportion,

maxSize,

maxWidth,

maxHeight,

imgWidth,

imgHeight,

(e) => {

data.push(e);

if (data.length == files.length) {

cb(data, loading);

}

},

() => {

cb([], loading);

}

);

status.push(fr);

}

} else {

cb([], loading);

}

});

}

//上传图片

export function chooseImg({

cb,

max = 1,

proportion = '',

maxSize = 2048,

maxWidth = 0,

maxHeight = 0,

imgWidth = 0,

imgHeight = 0,

}) {

chooseFile({

max,

accept: 'image/*',

proportion,

maxSize,

maxWidth,

maxHeight,

imgWidth,

imgHeight,

cb,

});

}

使用chooseFile上传文件

chooseFile({

cb: (files) => {

if (files.length) {

files.forEach(async (i) => {

const results = await uploadFile({

data: i.file,

fileName: 'SERVICE' + new Date().getTime() + i.file.name,

dir: 'FILE',

});

console.log(results.url)

});

} else {

notification['error']({

message: '上传失败',

});

}

},

max: 100,

});

使用 chooseImg 上传照片

chooseImg({

cb: async (files) => {

console.log(files);

if (files.length) {

const results = await uploadFile({

data: files[0].file,

fileName: 'IMGURL' + new Date().getTime(),

dir: 'IMG',

});

console.log(results);

} else {

notification['error']({

message: '上传失败',

});

}

},

maxSize: 1024, //图片大小

imgWidth: 220, //图片宽

imgHeight: 220, //图片高

});

buildShortUUID文件

const hexList: string[] = [];

for (let i = 0; i <= 15; i++) {

hexList[i] = i.toString(16);

}

export function buildUUID(): string {

let uuid = '';

for (let i = 1; i <= 36; i++) {

if (i === 9 || i === 14 || i === 19 || i === 24) {

uuid += '-';

} else if (i === 15) {

uuid += 4;

} else if (i === 20) {

uuid += hexList[(Math.random() * 4) | 8];

} else {

uuid += hexList[(Math.random() * 16) | 0];

}

}

return uuid.replace(/-/g, '');

}

let unique = 0;

export function buildShortUUID(prefix = ''): string {

const time = Date.now();

const random = Math.floor(Math.random() * 1000000000);

unique++;

return prefix + '_' + random + unique;

}

文件转base64 base64Conver

/**

* @description: base64 转 blob

*/

export function dataURLtoBlob(base64Buf: string): Blob {

const arr = base64Buf.split(',');

const typeItem = arr[0];

const mime = typeItem.match(/:(.*?);/)![1];

const bstr = atob(arr[1]);

let n = bstr.length;

const u8arr = new Uint8Array(n);

while (n--) {

u8arr[n] = bstr.charCodeAt(n);

}

return new Blob([u8arr], { type: mime });

}

/**

* img url to base64

* @param url

*/

export function urlToBase64(url: string, mineType?: string): Promise {

return new Promise((resolve, reject) => {

let canvas = document.createElement('CANVAS') as Nullable;

const ctx = canvas!.getContext('2d');

const img = new Image();

img.crossOrigin = '';

img.onload = function () {

if (!canvas || !ctx) {

return reject();

}

canvas.height = img.height;

canvas.width = img.width;

ctx.drawImage(img, 0, 0);

const dataURL = canvas.toDataURL(mineType || 'image/png');

canvas = null;

resolve(dataURL);

};

img.src = url;

});

}

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: