uni-app的uni.upload上传图片报错

前言

Uniapp真是个大坑?不管你是否赞同这个观点,反正我是这么认为的。 但是,又没有开发原生的成本和精力,所以就跟鸡肋一样。 食之无味,弃之可惜。

今天我就分享一下我遇到的一个坑。

开始

项目需求,移动端上传图片,一下就想到使用uniapp自带的上传组件

这里用到的是vue3写法

vue 复制代码
 <uni-file-picker ref="images"> </uni-file-picker>

如果是多张图片的上传,遍历images内的filesList数组

javaScript 复制代码
    const sceneFileImgs = [];
    if (images.value.filesList && images.value.filesList.length > 0) {
      images.value.filesList.forEach((i, index) => {
        sceneFileImgs.push({ name: `sceneFileImgs[${index}].png`, uri: i.url });
      });
    }

按照Uniapp的文档,字段名称格式为

这里files的对象名称要根据接口来定。

他们要的字段是什么名字,你就跟他命名一致,像我这里是sceneFileImgs formData 是接口需要提交的额外参数,这里不用 再包含 sceneFileImgs

javaScript 复制代码
    uni.uploadFile({
      url:'https://juejin.cn/api/submit',
      files: sceneFileImgs,
      header: {
        Authorization: uni.getStorageSync('token'),
      },
      formData: formDatas,
      complete: res => {
        if (data.code === 0) {
          toast('提交成功');
        } else {
          toast(`${data.msg}`);
        }
      },
    });

H5上开始调试,完美!

Android上调试,完美!

但是!

IOS就会失败,接口都没有进行请求

黑人问号

网上搜了一圈,说是IOS在接口上要强制手动添加 'Content-Type': 'multipart/form-data'

但是

加上去之后发现,后端报错了

这啥问题呢?

报错提示后端在解析你的请求头时,发现在你的请求头里没有找到 boundary

boundary 就是formData数据的分隔符,

所以,正是因为你写了content-type之后,覆盖了浏览器自己帮你拼上的boundary

那怎么办?

那好,咱获取一下formDataboundary ,再拼到请求头上。

想法太天真了

因为boundary 获取不到,前端无论你在哪里都获取不到

所以陷入了死循环

那到底怎么解决呢?

只能放弃uniapp提供的upload方法

自己定义接口,使用axios或者ajax,这样IOS在请求的时候会自动 给你加上Content-Type

接下来就是见证奇迹的时候

附录

附上自定义的接口代码

JavaScript 复制代码
    const sceneFileImgs = [];
    if (images.value.filesList && images.value.filesList.length > 0) {
      images.value.filesList.forEach((i, index) => {
        sceneFileImgs.push({ name: i.name, uri: i.url });
      });
    }
    Object.keys(formDatasClone).forEach(key => {
        formData.append(key, formDatasClone[key]);
      });
    // 请求头的配置,不需要再配置 Content-Type
    // 无论是IOS还是安卓都会自动帮你添加上去
    const config = {
        headers: {
          Authorization: uni.getStorageSync('token'),
        },
    };
    for (let index = 0; index < sceneFileImgs.length; index++) {
        const el = sceneFileImgs[index];
        // 将blodUrl 转换成 File格式
        await getFileFromUrl(el.uri, el.name)
          .then(response => {
            formData.append(`sceneFileImgs[${index}]`, response);
          })
      }

      axios.post('https://juejin.cn/api/submit', formData, config).then(res => {
        if (res.data.code === 0) {
          toast('提交成功');
        } else {
          toast(`${res.data.msg}`);
        }
      })

getFileFromUrl函数

JavaScript 复制代码
  // 将blodUrl 转换成 File格式
  const getFileFromUrl = (url, fileName) => {
    return new Promise((resolve, reject) => {
      var blob = null;
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.setRequestHeader('Accept', 'image/png');
      xhr.responseType = 'blob';
      // 加载时处理
      xhr.onload = async () => {
        // 获取返回结果
        blob = xhr.response;
        let file = new File([blob], fileName, { type: 'image/png' });
        resolve(file);
      };
      xhr.onerror = e => {
        reject(e);
      };
      // 发送
      xhr.send();
    });
  };

后续

移动端上传的图片太大,我们可以进行压缩处理 在getFileFromUrl函数返回file结果进行压缩

相关推荐
CharlesYu0110 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
Bs_MoneyMagnet10 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
平头哥技术团队10 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰11 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面11 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方12 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结12 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言13 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒13 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机13 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生