Arco Design Vue 中的a-upload

组件:

<a-upload

style="display: inline-block;width:auto;"

:file-list="item.fileList"

@success="uploadSuccess($event)"

@change="uploadChange($event,item.fileList,item)"

@error="uploadError($event)"

:custom-request="customUpload"

>

<template #upload-button>

<a-button type="outline"><icon-upload class="margin-right-10" />上传文件</a-button>

</template>

</a-upload>

函数:

import { getToken } from '@/utils/auth';

import {

ref,

} from 'vue';

import md5 from 'md5';

import axios from 'axios';

import { Message } from '@arco-design/web-vue';

export const customUpload=async(options:any)=>{

//-begin--不用全局的,用局部的获取headers----

const token = getToken();

const timestamp = ref(Date.parse(new Date().toString()) / 1000);

const passstr = ref(md5(import.meta.env.VITE_ENCRYPT + timestamp.value));

const headers_msg = ref({

apiverify: window.btoa(passstr.value + '#' + timestamp.value),

Authorization: token,

});

const action = window?.globalConfig.Root_url_dev + '/upload';

// -end----------

// console.log("options---->",options);

/**

* options:由 a-upload 传入的对象,包含以下关键字段:

fileItem: 当前上传的文件对象(含 file 属性)

onProgress(percent, file): 通知上传进度的回调

onSuccess(response, file): 上传成功时调用

onError(error): 上传失败时调用

*/

const {fileItem,onProgress,onSuccess,onError} = options;

const formData=new FormData(); //将用户选择的文件附加到 FormData 中,用于 multipart/form-data 请求。

formData.append('file',fileItem.file);

/**

* 使用 setTimeout 手动触发取消(防止 axios 内置 timeout 在某些环境下失效);

同时配合 axios.CancelToken 实现请求取消。

*/

//设置超时时间 (单位:毫秒)

const TIMEOUT=1000*60*30; //30分钟

//方案1:使用axios 的CancelToken

const source=axios.CancelToken.source(); //

//设置超时定时器

const timeoutTimer=setTimeout(()=>{

source.cancel(`上传超时(${TIMEOUT/1000}秒)`);

},TIMEOUT);

try{

//发送请求

console.log('headers.value', headers_msg.value);

/**

* action:上传接口地址(来自组件外部定义);

headers.value:包含认证 token 和时间戳签名(防重放攻击);

onUploadProgress:实时更新上传进度条。

*/

const response=await axios.post(action,formData,{

headers:{

...headers_msg.value,

'Content-Type':'multipart/form-data'

},

cancelToken:source.token,

timeout:TIMEOUT, // axios 内置超时

/* onUploadProgress:(progressEvent)=>{

console.log("上传进度--》",progressEvent);

if(progressEvent.lengthComputable){

const percent=Math.round(

(progressEvent.loaded * 100) / progressEvent.total

)

onProgress(percent,fileItem.file);

}

} */

});

/**

* 清除超时定时器;

调用 onSuccess,传递后端返回的数据(response.data),符合 a-upload 预期格式。

*/

//调用进度回调

//清除超时定时器

clearTimeout(timeoutTimer);

console.log('response', response);

//调用成功回调

onSuccess({

response:response.data, //保持与原来相同的结构

file:fileItem.file

})

}catch(error:Error|any){

console.log("error--->",error);

//清除超时定时器

if(timeoutTimer) clearTimeout(timeoutTimer);

let errorMessage = '上传失败';

if(axios.isCancel(error)){

errorMessage = error.message; // 上传超过 30秒

}else if(error.code === 'ECONNABORTED'){

errorMessage='请求超时,请检查网络连接';

}else if(error.response){

errorMessage=error.response.data?.message || `服务器错误:${error.response.status}`;

}else if(error.request){

errorMessage='请求失败,请检查网络连接';

}

//调用错误回调

onError(new Error(errorMessage));

}

}

export const uploadSuccess=(res: any) =>{

// console.log('itemvalue--->', itemvalue);

// console.log('item--->', item);

console.log('上传成功', res);

const resp_msg=res?.response?.response;

if(resp_msg?.code == 0){

Message.success('上传成功');

}else{

Message.error(resp_msg?.message);

}

}

export const uploadError=(res: any)=> {

console.log('上传失败', res);

Message.error(res?.response?.message);

}

/**

* const formData = new FormData();

formData.append('file', fileItem.file);

定义:FormData 是浏览器原生提供的一个构造函数,用于构建表单数据,特别适用于通过 XMLHttpRequest 或 fetch/axios 发送 multipart/form-data 格式的请求(常用于文件上传)。

用途:

可以动态添加键值对(包括文件、字符串等);

自动设置正确的 Content-Type(含 boundary);

被 axios.post() 等方法识别并正确编码。

*/

/**

* const source = axios.CancelToken.source();

定义:这是 Axios 提供的一种请求取消机制(虽然现在已 deprecated,但仍在广泛使用)。

返回值:source 是一个对象,包含两个属性:

token:一个取消令牌(CancelToken),传给 axios 请求;

cancel(message?):一个函数,调用它即可取消使用该 token 的请求。

⚠️ 注意:Axios 官方推荐未来改用 AbortController,但当前代码仍有效。

*/

/**

* await axios.post(action, formData, {

cancelToken: source.token,

// ...

});

作用:将 source.token 传递给 axios 请求,绑定取消能力。

效果:

如果后续调用了 source.cancel('reason'),这个请求会立即被中断,并抛出一个特殊的错误(可通过 axios.isCancel(error) 判断);

常用于:超时控制、用户手动取消、组件卸载时清理请求等场景。

*/

//

// 🔜 建议(面向未来)

// 虽然当前代码能正常工作,但因 CancelToken 已废弃,长期建议迁移到 AbortController:

/* const controller = new AbortController();

// 设置超时

const timeoutTimer = setTimeout(() => {

controller.abort();

}, TIMEOUT);

try {

const response = await axios.post(action, formData, {

headers: { ... },

signal: controller.signal, // 替代 cancelToken

timeout: TIMEOUT,

});

} catch (error) {

if (axios.isCancel(error) || error.name === 'AbortError') {

// 处理取消

}

} */

//

相关推荐
96772 小时前
最简单版web server
前端
VT.馒头2 小时前
【力扣】2637. 有时间限制的 Promise 对象
前端·javascript·leetcode·typescript
zhengxianyi5152 小时前
Vue2 打包部署后通过修改配置文件修改全局变量——实时生效
前端·vue.js·前后端分离·数据大屏·ruoyi-vue-pro
灵犀坠2 小时前
Vue3 实现音乐播放器歌词功能:解析、匹配、滚动一站式教程
开发语言·前端·javascript·vue.js
north_eagle2 小时前
ReAct 框架详解
前端·react.js·前端框架
纟 冬2 小时前
React Native for OpenHarmony 实战:待办事项实现
javascript·react native·react.js
OEC小胖胖2 小时前
13|React Server Components(RSC)在仓库中的落点与边界
前端·react.js·前端框架·react·开源库
OEC小胖胖2 小时前
14|Hook 的实现视角:从 API 到 Fiber Update Queue 的连接点
前端·react.js·前端框架·react·开源库
i7i8i9com2 小时前
React 19学习基础-2 新特性
javascript·学习·react.js