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

使用Node.js+Multer将图片以Blob存入MySQL后,无法通过Object URL显示图片的问题求助

使用Node.js+Multer将图片以Blob存入MySQL后,无法通过Object URL显示图片的问题求助

问题描述

我正在开发一个图片上传与展示功能:前端通过AJAX上传图片,后端用Express+Multer接收后将图片以Blob格式存入MySQL数据库,之后从数据库取出图片并在前端用Object URL显示。目前上传流程提示成功,但取出后图片无法正常显示,想请教问题出在哪里?

我的现有代码

1. 前端上传逻辑(index.html)

input.addEventListener('change', function () {
  uploadIMagetoDatabase(input.files[0]);
  getIMagefromDatabase(imgtag);
});

function uploadIMagetoDatabase(image){
  var data, xhr;
  data = new FormData();
  data.append('imageProfile', image);
  xhr = new XMLHttpRequest();
  xhr.open('POST', 'http://localhost:3000/upload', true);
  xhr.onreadystatechange = function (response) {
    // document.getElementById("result").innerHTML = xhr.responseText
  };
  xhr.send(data);
}

2. 后端上传接口(Express.js)

router.post('/upload', upload.single('imageProfile'),function(req,res){
  const imageProfile = req.file;
  var image=imageProfile;
  var sql='Insert into Uploads (id,image) VALUES("2",cast("'+image+'" AS BINARY));';
  connection.query(sql, function (err, data) {
    if (err) {
      console.log("database error-----------"+err);
    } else {
      console.log("database insert sucessfull-----------");
    }
  });
});

3. 后端图片获取接口(Express.js)

router.get('/getimage',function(req,res){
  var sql = 'SELECT image FROM Uploads';
  connection.query(sql, function (err, data) {
    if (err) {
      console.log("database error-----------"+err);
    } else {
      console.log("database select sucessfull-----------"+data.length);
      res.json({'image':data[0].image});
    }
  });
});

4. 前端图片展示逻辑(index.html)

function getIMagefromDatabase(imgtag){
  $.get("http://localhost:3000/getimage",function(data,status){
    console.log("data---"+JSON.stringify(data));
    let url = URL.createObjectURL(
      new Blob([data["image"]], { type: 'image/jpeg' })
    )
    imgtag.src=url;
  });
}

异常现象

  • 上传后控制台提示数据库插入成功,但接口返回的图片数据是:{"image":{"type":"Buffer","data": [91,111,98,106,101,99,116,32,79,98,106,101,99,116,93]}},这个data数组对应字符串[object Object]的ASCII码,显然不是图片二进制内容
  • 前端生成Object URL后,img标签无法渲染出图片

问题根源与修复方案

1. 核心问题:上传时未存入正确的图片二进制数据

当前上传代码直接将req.file(一个对象)拼接到SQL中,实际存入数据库的是字符串[object Object]的二进制形式,而非图片本身的内容。同时字符串拼接SQL存在注入风险。

修复后的上传接口:

router.post('/upload', upload.single('imageProfile'), function(req, res) {
  const imageProfile = req.file;
  if (!imageProfile) {
    return res.status(400).send('No image uploaded');
  }
  // 使用参数化查询,传入图片的原始二进制buffer
  const sql = 'INSERT INTO Uploads (id, image) VALUES (?, ?)';
  connection.query(sql, ["2", imageProfile.buffer], function(err, data) {
    if (err) {
      console.log("database error-----------" + err);
      res.status(500).send('Database error');
    } else {
      console.log("database insert successful-----------");
      res.send('Upload successful');
    }
  });
});
  • 用imageProfile.buffer获取图片的真实二进制内容
  • 使用参数化查询(?占位符),让MySQL驱动自动处理二进制数据的正确存储,同时避免SQL注入

2. 优化图片获取逻辑:直接返回二进制数据

返回JSON格式的Buffer对象会增加前端处理成本,更合理的方式是直接返回图片二进制数据并设置正确的响应头:

修复后的获取接口:

router.get('/getimage', function(req, res) {
  // 建议指定id查询,避免返回多条数据
  const sql = 'SELECT image FROM Uploads WHERE id = ?';
  connection.query(sql, ["2"], function(err, data) {
    if (err) {
      console.log("database error-----------" + err);
      res.status(500).send('Database error');
    } else {
      if (data.length === 0) {
        return res.status(404).send('Image not found');
      }
      console.log("database select successful-----------");
      // 假设存储的是jpeg格式,若需要适配多格式,可在上传时将imageProfile.mimetype存入数据库
      res.setHeader('Content-Type', 'image/jpeg');
      // 直接发送图片二进制数据
      res.send(data[0].image);
    }
  });
});

简化后的前端展示逻辑:

function getIMagefromDatabase(imgtag) {
  // 直接将接口地址设为img的src,无需额外处理
  imgtag.src = 'http://localhost:3000/getimage';
}

3. 备选方案:通过Base64传输二进制数据(不推荐)

如果必须用JSON返回,可将二进制转成Base64字符串:

后端修改:

router.get('/getimage', function(req, res) {
  const sql = 'SELECT image FROM Uploads WHERE id = ?';
  connection.query(sql, ["2"], function(err, data) {
    if (err) {
      console.log("database error-----------" + err);
      res.status(500).send('Database error');
    } else {
      if (data.length === 0) {
        return res.status(404).send('Image not found');
      }
      // 将Buffer转成Base64字符串
      const imageBase64 = data[0].image.toString('base64');
      res.json({ image: imageBase64, mimeType: 'image/jpeg' });
    }
  });
});

前端修改:

function getIMagefromDatabase(imgtag) {
  $.get("http://localhost:3000/getimage", function(data, status) {
    // 将Base64转回Blob并生成Object URL
    const byteCharacters = atob(data.image);
    const byteNumbers = Array.from(byteCharacters, c => c.charCodeAt(0));
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: data.mimeType });
    const url = URL.createObjectURL(blob);
    imgtag.src = url;
  });
}

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:04:31