You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@mysql/xdevapi将ArrayBuffer存入MySQL Blob异常及回读方案咨询

问题背景

需要实现通过HTML input控件获取用户上传的文件(以图片为主,支持任意类型),借助@mysql/xdevapi将文件对应的ArrayBuffer存入MySQL的Blob类型字段。

所用技术栈

  • 客户端框架:Angular + Electron.js
  • 数据库连接:通过@mysql/xdevapi实现MySQL访问

已实现逻辑

  1. 监听input控件获取用户选择的文件,代码如下:
processInputFile(event) {
var file: File = event.target.files[0];
file.arrayBuffer().then((value) => {
  this.fileToStore = value;
});
}
  1. 编写MySQL更新逻辑,目标为更新step表的user_comment、user_file字段,代码如下:
UpdateStep = (step: TestSteps, fileToStore: ArrayBuffer): Promise<void> => {
    return new Promise<void>((resolve, reject) => {

        if (this.session === undefined) {
            reject(new Error('session is undefined'));
            return;
        }
        var sch = this.session.getSchema("gtb");
        var step_table = sch.getTable('step');
        step_table.update().set('user_comment', step.user_comment).set('user_file', fileToStore).where('id = ' + step.id).execute().catch(error => { console.error(error); });
        resolve();
    })
}

异常现象

原始文件大小为165KB,但从MySQL Workbench中下载存储的Blob字段内容仅得到2KB的无效文件,需要定位问题原因,同时实现从数据库读取对应文件、支持用户下载的完整逻辑。

问题根因

存入文件体积异常由两个问题共同导致:

  • 异步逻辑错误:调用execute()后未等待数据库写入操作执行完成就直接触发resolve(),写入过程抛出的类型不匹配、连接异常等错误仅在内部catch打印日志,没有向外抛出,外层逻辑无法感知写入失败,经常出现流程走完但数据未正常落库的情况。
  • 二进制参数类型不匹配:@mysql/xdevapi不支持直接识别原生ArrayBuffer作为Blob字段入参,直接传入时驱动会将ArrayBuffer转为对象字符串标识(类似[object ArrayBuffer]的短文本)存入字段,完全没有写入真实的二进制文件内容,这是文件体积只有2KB的核心原因。
修复方案

1. 写入逻辑修复

首先需要将前端拿到的ArrayBuffer转为Node.js原生Buffer类型(Electron环境下可直接调用Node API,无需额外依赖),这是@mysql/xdevapi识别Blob二进制类型的正确格式,同时修正Promise异步等待逻辑,确保写入完成后再返回结果。
修正后的写入代码:

UpdateStep = (step: TestSteps, fileToStore: ArrayBuffer): Promise<void> => {
    return new Promise<void>(async (resolve, reject) => {
        try {
            if (this.session === undefined) {
                throw new Error('session is undefined');
            }
            // 核心转换:ArrayBuffer转Node.js Buffer,适配xdevapi的Blob入参要求
            const fileBuffer = Buffer.from(fileToStore);
            const sch = this.session.getSchema("gtb");
            const step_table = sch.getTable('step');
            // 等待写入执行完成再返回,改用参数绑定避免SQL注入
            await step_table.update()
                .set('user_comment', step.user_comment)
                .set('user_file', fileBuffer)
                .where('id = :stepId')
                .bind('stepId', step.id)
                .execute();
            resolve();
        } catch (error) {
            console.error(error);
            reject(error);
        }
    })
}

字段类型提示:MySQL的TINYBLOB类型最大仅支持存储255KB内容,超过就会自动截断。如果后续需要存储更大的文件,建议将user_file字段类型修改为MEDIUMBLOB(最大支持16MB)或LONGBLOB(最大支持4GB)。

优化建议:建议在step表额外新增file_name(存储原始文件名)、file_mime(存储文件MIME类型)两个字段,避免下载时出现文件后缀不匹配、无法正常打开的问题。

2. 文件读取与下载逻辑实现

从xdevapi读取到的Blob字段值本身就是Buffer类型,可以直接转为前端Blob对象,通过临时URL触发浏览器下载,示例代码:

// 读取数据库存储的文件
const getStepFile = async (stepId: number): Promise<{fileName: string, fileBuffer: Buffer, mime: string}> => {
    const sch = this.session.getSchema("gtb");
    const step_table = sch.getTable('step');
    const result = await step_table.select('user_file', 'file_name', 'file_mime')
        .where('id = :id')
        .bind('id', stepId)
        .execute();
    const rows = result.fetchAll();
    if (rows.length === 0) throw new Error('对应步骤的文件记录不存在');
    return {
        fileBuffer: rows[0][0],
        fileName: rows[0][1],
        mime: rows[0][2]
    }
}

// 触发用户下载
const downloadStepFile = async (stepId: number) => {
    const { fileBuffer, fileName, mime } = await getStepFile(stepId);
    // 转为前端Blob对象,指定正确MIME类型
    const blob = new Blob([fileBuffer], { type: mime });
    const tempUrl = URL.createObjectURL(blob);
    // 创建临时a标签触发下载
    const downloadLink = document.createElement('a');
    downloadLink.href = tempUrl;
    downloadLink.download = fileName;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    // 清理临时DOM和URL对象
    document.body.removeChild(downloadLink);
    URL.revokeObjectURL(tempUrl);
}

内容的提问来源于stack exchange,提问作者Mosky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:36:32