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') {

// 处理取消

}

} */

//

相关推荐
掘了几秒前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅25 分钟前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅1 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊1 小时前
jwt介绍
前端
爱敲代码的小鱼1 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
NEXT062 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法