将base64图片以form-data格式上传到图片服务器

2,396 阅读1分钟

1. 思路

  1. base64格式的图片处理为Blob对象。
  2. Blob对象添加到formData对象中。
  3. http请求头设置为context-type: multipart/form-data上送到文件服务器。

2. 将base64图片转为Blob对象。

  1. 分隔base64编码串。将开头的文件类型和后面的编码分开。如下图:

image-20220527145411576.png

  1. 正则匹配获取文件类型: image/jpeg

  2. window.atob()解析base64编码,charCodeAt转为UTF-16ASCII,创建数组,将ASCII放进去。当打印 arrayBuffer后你会发现,里面有Uint8Array私有属性,并且该对象里面有对应的ASCII值,如下图

image-20220527153127676.png

  1. new Blob传入处理好的含有ASCII的数组。

代码实现:

function base64ToBlob(base64Data) {
  
  const dataArr = base64Data.split(','); // 根据,来分隔
  
  const imageType = dataArr[0].match(/:(.*?);/)[1]; // 获取文件类型。使用正则捕获 image/jpeg
  
  const textData = window.atob(dataArr[1]); // 使用atob() 将base64 转为文本文件
  const arrayBuffer = new ArrayBuffer(textData.length); // 创建一个二进制数据缓冲区,可以理解为一个数组
  const uint8Array = new Uint8Array(arrayBuffer); // 创建一个类型化数组对象,可以理解为上面的数组的成员,给这个对象赋值就会放到上面的数组中。
  for(let i = 0; i < textData.length; i++) {
    uint8Array[i] = textData.charCodeAt(i); // 将文本文件转为UTF-16的ASCII, 放到类型化数组对象中
  }
  
  return [new Blob([arrayBuffer], { type: imageType }), imageType.slice(6)]; // 返回两个值,一个Blob对象,一个图片格式(如jpeg)
}

3. 将Blob对象添加到formData对象中

  1. new FormData ,传入处理好的blob使用append方法添加表单

代码实现

function toFormData(base64Data) {
  const [imageBlob, imageType] = base64ToBlob(base64Data);  // 获取处理好的Blob 和文件类型
  const formData = new FormData();
  formData.append('file', imageBlob, `${Date.now()}.${imageType}`); // 添加到表单,传入文件名
  return formData;
}

4. http请求头设置为context-type: multipart/form-data上送到文件服务器

直接上代码

import axios from 'axios'; // 使用的是axios// 上传到照片服务器
function httpRequest(formData) {
    return axios({
        method: 'post',
        url: '', // 你的文件服务器地址
        data: formData,
        timeout: 60000,
        headers: {
            'Content-Type': 'multipart/form-data', // 请求头要设置为 form-data
            'Cache-Control': 'no-cache',
        },
    });
}

5. 完整代码

import axios from 'axios'; // 使用的是axios// base64 转为Blob
function base64ToBlob(base64Data) {
  
  const dataArr = base64Data.split(','); // 根据,来分隔
  
  const imageType = dataArr[0].match(/:(.*?);/)[1]; // 获取文件类型。使用正则捕获 image/jpeg
  
  const textData = window.atob(dataArr[1]); // 使用atob() 将base64 转为文本文件
  const arrayBuffer = new ArrayBuffer(textData.length); // 创建一个二进制数据缓冲区,可以理解为一个数组
  const uint8Array = new Uint8Array(arrayBuffer); // 创建一个类型化数组对象,可以理解为上面的数组的成员,给这个对象赋值就会放到上面的数组中。
  for(let i = 0; i < textData.length; i++) {
    uint8Array[i] = textData.charCodeAt(i); // 将文本文件转为UTF-16的ASCII, 放到类型化数组对象中
  }
  
  return [new Blob([arrayBuffer], { type: imageType }), imageType.slice(6)]; // 返回两个值,一个Blob对象,一个图片格式(如jpeg)
}
​
// 转为formData
function toFormData(base64Data) {
  const [imageBlob, imageType] = base64ToBlob(base64Data);  // 获取处理好的Blob 和文件类型
  const formData = new FormData();
  formData.append('file', imageBlob, `${Date.now()}.${imageType}`); // 添加到表单,传入文件名
  return formData;
}
​
// 上传请求
function httpRequest(formData) {
    return axios({
        method: 'post',
        url: '', // 你的文件服务器地址
        data: formData,
        timeout: 60000,
        headers: {
            'Content-Type': 'multipart/form-data', // 请求头要设置为 form-data
            'Cache-Control': 'no-cache',
        },
    });
}
​
// 上传到照片服务器
export default function upload(base64Data) {
    const formData = toFormData(base64Data);
    return new Promise((resolve, reject) => {
        httpRequest(formData).then((res: any) => {
            if (res.status === 200 && res.data.success === 1) {
                resolve(res.data.path);
            } else {
                reject(res.data);
            }
        }).catch((err) => {
            reject(err);
        });
    });
}