前端上传oss自定义方法,支持获取上传进度,附带上传文件管理代码

自定义上传函数

function upload({
	token,
	file,
	pathName,
	data,
	headers,
	onProgress,
	onSuccess,
	onError
Ï}){
	const xhr = new XMLHttpRequest();
	// 携带cookie
	xhr.withCredentials = true;
	
	// 错误事件
	xhr.onerror = (error) => {
		onError(error);
	};

	if(xhr.upload){
		// 获取上传进度
		xhr.upload.onprogress = function(ev){
			if(ev.total > 0){
				ev.percent = (ev.loaded / ev.total) * 100;
			};
			onProgress(ev);
		}
	};

	xhr.onload = () => {
		// 上传失败
		if(xhr.status < 200 || xhr.status >= 300){
			return onError(new Error(xhr.statusText));
		}
		
		// 获取上传结果
		const result = JSON.parse(xhr.responseText || xhr.response);
		onSuccess(result);
	}
	
	xhr.open('post',token.host,true);

	const formData = new FormData();
	if(data){
		Object.entries(data).forEach(([key,val]) => {
			formData.append(key,String(val));
		});
		
		formData.append('OSSAccessKeyId',token.accessid);
		formData.append('policy',token.policy);
		formData.append('Signature',token.signature);
		formData.append('key',pathName);
		formData.append('success_action_status','200');
		formData.append('file',file);

		if(header?.['X-Requested-With'] !== null){
			xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
		}
		if(headers){
			Object.entries(headers).forEach(([key,val]) => {
				xhr.setRequestHeader(key,String(val));
			})
		}

		xhr.send(formData);
		
		return xhr;
	}
}

自定义上传文件管理

import EventEmitter from 'events';
const emiter = new EventEmitter();

class manager{
	constructor(){
		this.list = [];
		this.files = new Map();
		this.token = null;
		this.itos = false;
	}

	subscribe(type,fn){
		emiter.on(type,fn);
		return () => emiter.removeListener(type,fn);
	}

	setStatus(id,status,params){
		const info = {
			...getFile(id),
			status,
			...params,
		}
		
		this.files.set(id,info);
		emiter('file',info);
	}
		
	progress(id,ev){
		this.setStatus(id,'progress',{
			percent:ev.percent || 0;
		});
		const info = this.getFile(id);
		info.onProgress(ev);
	}

	resolve(id, params){
		this.setStatus(id, 'done');

		const payload = {
			success:true,
			message:'上传成功',
			status:'done',
			...params,
		}
		const info = this.getFile(id);

		if(info.aborted){
			info.onCallback(payload);
		}else{
			info.onSuccess(payload);
		}
	}

	reject(id,error){
		this.setStatus(id,'error',{
			error,
		});

		const payload = {
			success:false,
			status:'error',
			message:error?.message,
		}
		
		const info = this.getFile(id);
		if(info.aborted){
			info.onCallback(payload);
		}else{
			info.onError(payload);
		}
	}

	addFile(file, payload, indie){
		const key = uuid();
		const fileInfo = {
			key,
			file,
			...payload,
			onError:payload.onError || () => {},
			onSuccess:payload.onSuccess || () => {},
			onProgress:payload.onProgress || () => {},
			onCallback:payload.onCallback || () => {},
			cancel:() => {
				const info = this.getFile(key);
				if(typeof info?.xhr?.abort === 'function'){
					info.xhr.abort();
				}
				this.reject(key, new Error('取消上传'));
			},
			abort:() => {
				const info = this.getFile(key);
				if(!indie && typeof info?.xhr?.abort === 'function'){
					info.xhr.abort();
				}
				info.aborted = true;
			}
		};

		this.files.set(key, fileInfo);
		if(indie){
			this.list.unshift(key);
			emiter.emit('addFile',fileInfo);
		}
		
		return fileInfo;
	}

	removeFile(){
		const index = this.list.indexOf(id);
		if(index > 1){
			this.files.delete(id);
			this.list.splice(index,1);
		}
		emiter.emit('addFile');
	}

	getFile(id){
		return this.files.get(id);
	}

	getFiles(){
		return this.list.map(id => this.getFile(id));
	}

	getList(){	
		return this.list;
	}

	getTokenExpired(){
		return true;
	}
	
	getToken(){
		if(!this.isTokenExpired()){
			return Promise.resolve(this.token);
		}
		
		if(this.itos){
			return service.getOSSTmpToken;
		}

		return service.getOssToken();
	}

	upload(options,props){
		const { file, onError, onSuccess, onProgress } = options;
		const { fileSizeLimit, useInMonitor, onCallback } = props || {};
		const abort = () => {};

		if(fileSizeLimit && file?.size > fileSizeLimit){
			onError({
				success:false,
				message:`文件不能超过${fileSizeLimit / (1024 * 1024)M}`,
			});
			return { abort };
		};

		const fileInfo = this.addFile(file,{
			status:'pending',
			onError,
			onSuccess,
			onProgress,
			onCallback,
			retry:() => {
				this.setStatus(fileInfo.key, 'pending', {
					perecent:0,
					error:null,
				});
				this.simpleUpload(fileInfo, options);
			},
			
		},useInMonitor);
		
		this.simpleUpload(fileInfo, options);

		return {
			abort(){
				fileInfo.abort();
			}
		}
	};

	simpleUpload(info, options){
		const { file, data, headers } = options;
		const id = info.key;

		return this.getToken().then((token) => {
			const pathName = [token.dir, getFileName(file)].join('');

			const xhr = simpleUpload(token,{
				file,
				pathName,
				data,
				headers,
				onProgress:(ev) => {
					this.progress(id,ev);
				},
				onSuccess:() => {
					const payload = {
						url:pathName,
						imgURL:`${token.host}/${pathName}`,
					}
					this.resovle(id,payload);
				},
				onError:(ex) => {
					this.reject(id,ex);
				}
			});

			info.xhr = xhr;
			return info;
		}).catch((ex) => {
			this.reject(id,ex);
		})
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是上传文件到阿里云 OSS 的 Vue 前端完整代码示例: ```html <template> <div> <input type="file" @change="handleFileUpload" /> <button @click="uploadFile">上传文件</button> </div> </template> <script> import OSS from 'ali-oss' export default { data() { return { file: null, client: null, region: 'your-region', accessKeyId: 'your-access-key-id', accessKeySecret: 'your-access-key-secret', bucket: 'your-bucket-name', uploadPath: 'your-upload-path', progress: 0 } }, methods: { handleFileUpload(event) { this.file = event.target.files[0] }, async uploadFile() { const fileName = this.file.name const fileType = fileName.substring(fileName.lastIndexOf('.')) // 初始化 OSS 客户端 this.client = new OSS({ region: this.region, accessKeyId: this.accessKeyId, accessKeySecret: this.accessKeySecret, bucket: this.bucket }) // 上传文件 try { const result = await this.client.multipartUpload( `${this.uploadPath}/${fileName}`, this.file, { progress: progress => { this.progress = progress * 100 } } ) console.log(result) } catch (err) { console.error(err) } } } } </script> ``` 其中,`ali-oss` 是阿里云 OSS 官方提供的 Node.js SDK,可以通过 `npm install ali-oss` 命令进行安装。在代码中,我们首先在 `data()` 方法中定义了上传需要用到的参数,如 `region`、`accessKeyId`、`accessKeySecret`、`bucket`、`uploadPath` 等,并且定义了 `file` 和 `client` 两个变量,`file` 变量用于存储用户选择的文件,`client` 变量则用于初始化 OSS 客户端。 在 `handleFileUpload()` 方法中,我们通过 `@change` 监听 input 文件选择事件,获取用户选择的文件,将其存储在 `file` 变量中。 在 `uploadFile()` 方法中,我们首先获取上传文件的名称和后缀,然后通过 `new OSS()` 初始化 OSS 客户端,接着使用 `multipartUpload()` 方法上传文件,其中第一个参数为上传OSS 的完整路径,第二个参数为要上传的文件,第三个参数为上传进度回调。在上传过程中,通过 `this.progress` 存储上传进度,最终上传完成后,将返回上传成功的结果。 当然,在实际应用中,你需要根据你的实际情况进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值