解决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的解析逻辑。希望这个方法能帮你少踩坑,高效完成文件上传功能!

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

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax