解决uni-app通用上传与后端接口不匹配问题:原生上传文件方法封装 ✨

在 uni-app 开发中,文件上传是高频需求 📤。 uni-app自带的uni.uploadFile虽便捷,但面对后端接口的个性化要求 时,常因参数格式、请求头限制等问题 "卡壳"。今天就分享一个我封装的原生上传方法 ,完美解决接口不匹配问题,还附带详细使用指南哦!

一、方法背景 📝

最近项目中,后端接口提出了 3 个 "特殊要求":

  1. 业务数据需以 Blob类型的 JSON 格式 传递 📦;

  2. 请求头必须携带自定义的 RequestId加密字段 🔑;

  3. 需实时展示文件上传进度 📊。

uni.uploadFile在「参数格式转换」和「自定义请求头」上存在局限,无法直接满足需求。因此,基于XMLHttpRequestFormData封装了这个原生上传方法,一次性解决所有痛点!

二、封装的上传文件方法代码 🚀

复制代码
// 引入基础地址和获取加密RequestId的方法

import { BASE_URL } from '@/config/requestConfig';

import { getEncrypted } from '@/utils/encryptionUtil';


// 自定义文件上传方法(解决uni.uploadFile接口不匹配问题)

// @param {Object} formDatas - 业务相关的参数数据(如作品名称、作者信息)

// @param {Array} files - 待上传文件数组(每个文件需含name和data属性)

// @returns {Promise} - 成功resolve结果,失败reject错误


export const upLoadWorks = (formDatas, files) => {

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

    // 1. 拼接完整上传接口地址(需替换为你的实际接口)

   const url = BASE_URL + '/auth/upload';

    // 2. 创建FormData承载参数和文件(核心容器)

   const formData = new FormData();


    // 🌟 关键:将业务参数转为Blob类型JSON(后端要求的格式)

    formData.append('teamWorksCustom', new Blob([JSON.stringify(formDatas)], {

     type: "application/json"

     }));


   // 🌟 关键:遍历文件数组,添加到FormData(支持多文件上传)

  files.map(file => {

    formData.append(file.name, file.data);

    });


   // 3. 初始化XMLHttpRequest(原生AJAX核心)

    const xhr = new XMLHttpRequest();

    xhr.open('POST', url, true); // 异步POST请求


    // 🌟 关键:设置自定义请求头(后端要求的RequestId)

    xhr.setRequestHeader('RequestId', await getEncrypted());


    // 🌟 关键:监听上传进度(实时展示给用户)

   xhr.upload.onprogress = function(event) {

    if (event.lengthComputable) {

    // 计算上传进度百分比

    let percentComplete = event.loaded / event.total;

  // 显示进度loading(提升用户体验)

   uni.showLoading({

   title: '已上传' + Math.floor((percentComplete * 100)) + '%',

    mask: true

    });

   } else {

    console.log('无法计算进度 📈');

    }

   };

   // 4. 处理请求结果

 xhr.onload = function() {

  uni.hideLoading(); // 关闭loading(无论成败都要关!)

  if (xhr.status === 200) {

  // 成功:解析JSON响应并返回

   resolve(JSON.parse(xhr.responseText));

   } else {

    // 失败:返回状态码(便于排查问题)

      reject(xhr.status);

    }

   };

  // 5. 处理请求错误(如网络异常)

  xhr.onerror = function(err) {

  uni.hideLoading();

  reject(err);

   console.error('请求出错 ❌', err);

  };

  // 6. 发送请求(核心步骤)

  xhr.send(formData);

 });

};

三、方法解析 🔍

1. 核心参数说明

参数名 类型 作用 注意事项
formDatas Object 业务参数(如作品名、作者) 必须转为Blob类型 JSON,否则后端无法解析!
files Array 待上传文件数组 每个文件需含 name(后端字段名)data(文件原始数据)

2. 3 个核心逻辑(必看!)

  • 📦 FormData 构建 :用FormData统一承载 "Blob 类型业务参数" 和 "文件数据",契合后端接口的参数格式要求;

  • 🔑 自定义请求头 :通过xhr.setRequestHeader添加RequestId,解决uni.uploadFile无法灵活设置请求头的问题;

  • 📊 进度监听xhr.upload.onprogress实时计算进度,搭配uni.showLoading让用户清晰感知上传状态,避免 "卡顿时误以为没反应"。

四、使用场景(精准匹配!)🎯

以下场景用这个方法,效率直接拉满:

  1. 后端要求特殊参数格式 📋:比如业务参数需Blob类型 JSON、多参数嵌套等,uni.uploadFile搞不定的情况;

  2. 需要自定义请求头 🔒:比如接口要求携带TokenRequestId等自定义字段,且需加密处理;

  3. 大文件上传需进度展示 📁:如视频、压缩包等大文件,进度条能极大提升用户体验;

  4. uni.uploadFile无法满足的其他场景 ❌:比如后端接口是 RESTful 风格、需自定义响应解析逻辑等。

五、适用的后台接口类型 🖥️

你的后端接口需满足以下 4 个条件,才能完美适配这个方法:

  1. ✅ 支持FormData 格式请求体 :能解析FormData中的 "Blob 参数" 和 "文件数据";

  2. ✅ 能识别自定义请求头 :能读取并验证RequestId等自定义字段;

  3. ✅ 返回JSON 格式响应 :方法会自动解析 JSON,若后端返回其他格式(如 XML)需修改resolve逻辑;

  4. ✅ 支持多文件上传 :能根据file.name(前端传的字段名)分别接收多个文件。

六、使用步骤(手把手教学!)📝

1. 准备依赖(先做这步!)

确保项目中已引入 2 个关键依赖:

  • BASE_URL:接口基础地址(如https://api.xxx.com);

  • getEncrypted():异步获取加密RequestId的方法(若后端不需要,可删除请求头相关代码)。

2. 3 步调用上传方法

(1)选择文件并转成 "文件数据"

用 Uniapp 的uni.chooseImage/uni.chooseVideo选文件,再通过uni.getFileSystemManager()将 "临时路径" 转成 "原始文件数据":

复制代码
// 选择图片示例(支持多选)

uni.chooseImage({

count: 3, // 最多选3张

 sizeType: ['original', 'compressed'], // 原图/压缩图

  sourceType: ['album', 'camera'], // 相册/相机

success: async (res) => {

 const tempFilePaths = res.tempFilePaths;

   const files = [];


    // 遍历临时路径,转成文件数据

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

    const tempFilePath = tempFilePaths[i];

      // 读取文件数据(关键步骤!)

     const fileData = await new Promise((resolve) => {

      uni.getFileSystemManager().readFile({

     filePath: tempFilePath,

    success: (fileRes) => {

     resolve(fileRes.data); // 拿到原始文件数据

  }

 });

  });


 // 添加到files数组(name要和后端字段名一致!)

  files.push({

  name: `image${i + 1}`, // 后端接收字段名,如image1、image2

  data: fileData

 });

  }


 // 调用上传方法(下一步讲)

 await uploadFiles(files);

}

});
(2)准备业务参数
复制代码
// 示例:业务参数(根据你的实际需求修改)

const formDatas = {

 workName: '我的旅行vlog', // 作品名

 author: '小明', // 作者

 teamId: 'team_123456', // 团队ID

  // 其他参数...

};
(3)调用方法并处理结果
复制代码
import { upLoadWorks } from '@/utils/uploadUtil'; // 引入方法

async function uploadFiles(files) {

 try {

  const formDatas = { workName: '我的旅行vlog', author: '小明' };

  // 调用上传方法

  const uploadResult = await upLoadWorks(formDatas, files);

  // 成功:提示+后续操作(如跳转页面)

  uni.showToast({ title: '上传成功 ✅', icon: 'success' });

 console.log('上传结果:', uploadResult);

 // 跳转页面示例:uni.navigateTo({ url: '/pages/success/success' });


 } catch (err) {

  // 失败:提示用户+记录错误(便于排查)

  uni.showToast({ title: '上传失败 ❌', icon: 'none' });

     console.error('上传错误:', err);

  }

}

七、注意事项(避坑指南!)⚠️

  1. 📁 文件数据必须转对 :如果直接传 "临时文件路径"(如res.tempFilePaths),会导致上传失败!必须用uni.getFileSystemManager().readFile转成原始文件数据;

  2. 🔑 RequestId 要有效getEncrypted()必须返回后端认可的加密值,否则会被接口拦截(若不需要,直接删除xhr.setRequestHeader这行);

  3. 📍 接口地址要改对url = BASE_URL + '/auth/upload'中的/auth/upload是示例接口,一定要替换成你的实际接口路径;

  4. 📱 兼容性测试 :该方法用了XMLHttpRequestFormData,在 Uniapp 的 H5、App 端基本没问题,但低版本小程序可能有兼容问题,上线前务必多端测试;

  5. 🚨 loading 必须关闭xhr.onloadxhr.onerror中都要加uni.hideLoading(),否则会出现 "loading 一直转" 的尴尬情况!

八、总结 📌

这个原生上传方法的核心价值,在于突破了 Uniapp 通用方法的限制,精准匹配后端接口的个性化需求。无论是 "特殊参数格式""自定义请求头",还是 "进度展示",都能一站式解决。

实际开发中,你可以根据后端接口的变化灵活调整:比如不需要RequestId就删请求头代码,后端返回非 JSON 就修改resolve的解析逻辑。希望这个方法能帮你少踩坑,高效完成文件上传功能!

如果有疑问或优化建议,欢迎在评论区交流哦~ 💬

相关推荐
listhi5207 小时前
CSS:现代Web设计的不同技术
前端·css
南囝coding8 小时前
现代Unix命令行工具革命:30个必备替代品完整指南
前端·后端
起风了___8 小时前
Flutter 多端音频控制台:基于 audio_service 实现 iOS、Android 锁屏与通知中心播放控制
前端·flutter
作业逆流成河8 小时前
🎉 enum-plus 发布新版本了!
前端·javascript·前端框架
WYiQIU8 小时前
高级Web前端开发工程师2025年面试题总结及参考答案【含刷题资源库】
前端·vue.js·面试·职场和发展·前端框架·reactjs·飞书
WuWuII8 小时前
SSE服务端单向推送消息到前端
前端·推送
.又是新的一天.8 小时前
04-Fiddler详解+抓包定位问题
前端·测试工具·fiddler
克里斯蒂亚L8 小时前
OpenLayers - 画全国轨道线路图
前端
GISer_Jing8 小时前
小米前端面试
前端·面试·职场和发展