uni-app中二进制流到Base64编码的转换

549 阅读3分钟

今天跟后端一起设计了一个图片上传的流程:

  • 将用户上传的图片信息通过formData数据发送给后端,后端存储后返回图片名给前端。
  • 前端调用函数,将图片名当做参数再次传递给后端,后端将图片的二进制流信息返回。
  • 前端将二进制流信息转为base64,展现在页面中,这样就完成了图片的上传,以及回显。

这里为什么要再次将图片名传递给后端呢,是因为我们不仅仅要完成图片的上传,还有图片信息的回显,当我们的数据中有图片名,就表示这个数据是用于回显的数据,就需要调用封装好的函数来实现图片的回显。

废话说完了,我们来回归标题中提到的怎么将二进制流文件转为base64编码

利用拦截器设置响应数据类型为arraybuffer

下面代码中我们根据请求的地址是否包含上传图片的地址,如果包含则需要给请求参数设置responseType为arraybuffer可以参考下面链接

👇👇👇👇👇👇👇👇

uni.request(OBJECT) | uni-app官网 (dcloud.net.cn)

image.png

function httpInterceptor(options) {
    // 请求前的拦截器逻辑
    const secretStore = userSecretStore();
    // 判断非http开头需要拼接参数
    if (!options.url.startsWith('http')) {
        options.url = baseUrl + options.url;
    }
    if (options.url.includes('getIdCardImage')) options.responseType = 'arraybuffer'; // 如果请求地址是图片上传,则需要设置请求类型为arraybuffer

    // 设置请求超时时间
    if (!options['timeout']) options.timeout = 10000;

    // 设置请求头
    options.header = {
        ...options.header,
        uniqueId: secretStore.uniqueid,
        iv: secretStore.iv,
    };
    return options;
}

在响应拦截器中检查是否是二进制数据,并进行相应转换

success: (response) => {
    // 响应拦截器逻辑

    // 检查是否是二进制数据响应
    if (response.data && response.data.constructor === ArrayBuffer) {
        const base64Data = uni.arrayBufferToBase64(response.data);
        response.data = 'data:image/png;base64,' + base64Data; // 如果是二进制流数据,则需要将二进制流数据转为bace64类型数据并回显
    }
    resolve(response.data); // 根据需要调整
},

这里使用到了uni.arrayBufferToBase64方法将 ArrayBuffer 对象转成 Base64 字符串

uni.arrayBufferToBase64(arrayBuffer) | uni-app官网 (dcloud.net.cn)

image.png

完整拦截器代码

const baseUrl = 'URL_ADDRESS';

function httpInterceptor(options) {
    // 判断非http开头需要拼接参数
    if (!options.url.startsWith('http')) {
        options.url = baseUrl + options.url;
    }
    if (options.url.includes('getIdCardImage')) options.responseType = 'arraybuffer'; // 如果请求地址是图片上传,则需要设置请求类型为arraybuffer

    // 设置请求超时时间
    if (!options['timeout']) options.timeout = 10000;

    // 设置请求头
    options.header = {
        ...options.header,
        // 可以自行添加数据
    };
    return options;
}

const request = (options) => {
    options = httpInterceptor(options); // 在发送请求前调用拦截器
    return new Promise((resolve, reject) => {
        uni.request({
            ...options,
            success: (response) => {
                // 响应拦截器逻辑
                // 检查是否是二进制数据响应
                if (response.data && response.data.constructor === ArrayBuffer) {
                    const base64Data = uni.arrayBufferToBase64(response.data);
                    response.data = 'data:image/png;base64,' + base64Data; // 如果是二进制流数据,则需要将二进制流数据转为bace64类型数据并回显
                }
                resolve(response.data); // 根据需要调整
            },
            fail: (error) => {
                if (error.errMsg.includes('timeout')) {
                    // 显示错误消息给用户
                    uni.showModal({
                        title: '网络错误',
                        content: '请求超时,请检查网络连接',
                        showCancel: false,
                        confirmColor: '#007AFF',
                        confirmText: '确定',
                    });
                } else {
                    // 非超时错误处理
                    reject(error);
                    uni.showModal({
                        title: '请求失败',
                        content: '请求失败,请重新尝试',
                        showCancel: false,
                        confirmColor: '#007AFF',
                        confirmText: '确定',
                    });
                }
            },
        });
    });
};
export default request;