【问题标题】:How to save & retrive image to/from mysql?如何在mysql中保存和检索图像?
【发布时间】:2020-09-06 02:00:00
【问题描述】:

两部分问题。

第 1 部分:

我正在将图像上传到我的服务器并希望将其保存到我的数据库中。

到目前为止:

表:

解析器:

registerPhoto: inSequence([
  async (obj, { file }) => {
    const { filename, mimetype, createReadStream } = await file;
    const stream = createReadStream();

    const t = await db.images.create({
      Name: 'test',
      imageData: stream ,
    });
  },
])

执行查询:

Executing (default): INSERT INTO `images` (`Id`,`imageData`,`Name`) VALUES (DEFAULT,?,?);

但什么都没有保存。

我对此很陌生,我可能错过了一些东西,但不知道是什么。

第 2 部分:

接下来是第 1 部分,假设我设法保存了图像,我如何读取它并将其发送回我的 FE?

编辑:我已经阅读了很多指南,将图像名称保存到数据库,然后将实际图像保存在文件夹中。这不是我想要的,想要将图像保存到数据库中,然后能够从数据库中获取它并呈现它。

【问题讨论】:

  • 在数据库中存储二进制数据总是不是一个好主意....流可以保存在数据库中吗? ...返回url,渲染,结束
  • 我知道但想将其保存到数据库中。学习经历。尝试将 stram 转换为 blob 但没有奏效。试图弄清楚这一点,任何链接将不胜感激。
  • eh....流无法保存在数据库中-您必须一次对整个数据(缓冲区)进行操作...内存消耗大的操作,这是不好的原因之一:D跨度>
  • @xadm,一倒一倒,搞定了缓冲区
  • 在 db 中存储有关存储在磁盘上的文件的信息 - 处理数据(关于文件)的好处,而无需(过多)担心它们在哪里(随机/均匀分布的文件夹结构 - 而不是一个可能是大/不可更改的文件夹) .... 阅读“为什么在 db 中存储文件不好”

标签: mysql express graphql sequelize.js fastify


【解决方案1】:

这花了我一些时间,但我终于弄明白了。

第一步(保存到数据库):

必须获取整个流数据并像这样读取它:

export const readStream = async (stream, encoding = 'utf8') => {
  stream.setEncoding('base64');

  return new Promise((resolve, reject) => {
    let data = '';

    // eslint-disable-next-line no-return-assign
    stream.on('data', chunk => (data += chunk));
    stream.on('end', () => resolve(data));
    stream.on('error', error => reject(error));
  });
};

这样使用:

const streamData = await readStream(stream);

在保存之前,我将流放入缓冲区:

const buff = Buffer.from(streamData);

最后是存档部分:

db.images.create(
            {
              Name: filename,
              imageData: buff,
              Length: stream.bytesRead,
              Type: mimetype,
            },
            { transaction: param }
          );

请注意,我添加了LengthType 参数,如果您希望在返回图像时返回流,则需要此参数。

第 2 步(检索图像)。

正如@xadm 多次所说,您不能从 GRAPHQL 返回图像,过了一段时间我不得不接受这个事实,希望 graphql 将来能解决这个问题。

S 我需要做的是在我的 fastify 后端设置一个路由,发送一个图像 ID 到这个路由,获取图像然后返回它。

我对此有一些不同的方法,但最后我简单地返回了一个二进制文件,并在前端将其编码为 base64。

后端部分:

const handler = async (req, reply) => {
  const p: postParams = req.params;

  const parser = uuIdParserT();

  const img = await db.images.findByPk(parser.setValueAsBIN(p.id));

  const binary = img.dataValues.imageData.toString('binary');

  const b = Buffer.from(binary);

  const myStream = new Readable({
    read() {
      this.push(Buffer.from(binary));
      this.push(null);
    },
  });
  reply.send(myStream);
};

export default (server: FastifyInstance) =>
  server.get<null, any>('/:id', opts, handler);

前端部分:

  useEffect(() => {
     // axiosState is the obj that holds the image
    if (!axiosState.loading && axiosState.data) {
      // @ts-ignore
      const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
        const byteCharacters = atob(b64Data);
        const byteArrays = [];

        for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
          const slice = byteCharacters.slice(offset, offset + sliceSize);

          const byteNumbers = new Array(slice.length);
          // @ts-ignore
          // eslint-disable-next-line no-plusplus
          for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
          }

          const byteArray = new Uint8Array(byteNumbers);
          byteArrays.push(byteArray);
        }

        const blob = new Blob(byteArrays, { type: contentType });
        return blob;
      };

      const blob = b64toBlob(axiosState.data, 'image/jpg');

      const urlCreator = window.URL || window.webkitURL;
      const imageUrl = urlCreator.createObjectURL(blob);
      setimgUpl(imageUrl);
    }
  }, [axiosState]);

最后在 html 中:

   <img src={imgUpl} alt="NO" className="imageUpload" />

其他: 对于尝试相同注意的任何人来说,这不是最佳实践。 我发现的几乎每一篇文章都将图像保存在服务器上,并将图像 ID 和其他元数据保存在数据库中。对于这方面的确切利弊,我发现以下内容很有帮助:

Storing Images in DB - Yea or Nay?

如果出于某种原因我想将图像保存在数据库中并最终解决它,我专注于找出如何做到这一点。

【讨论】:

【解决方案2】:

有两种方法可以将图像存储在 SQL 数据库中。您可以将实际图像存储在服务器上并将图像路径保存在 mySql db 中,或者使用图像创建 BLOB 并将其存储在 db 中。 这是一个方便的阅读https://www.technicalkeeda.com/nodejs-tutorials/nodejs-store-image-into-mysql-database

【讨论】:

  • 请点击我附加的链接。它有关于如何为 blob 配置 mySql 和用于添加新条目的 nodejs 脚本的大量示例
  • 我有,我面临的问题是该链接显示了如何存储在磁盘上使用的文件。我的是从前端上传的--->后端。 fs.readFileSync(file),给我错误类型错误 [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串、缓冲区或 URL 类型之一。接收到的类型对象
  • 想弄清楚如何创建 BLOB?我根本不想在磁盘上添加图像。
【解决方案3】:

您应该将图像保存在目录中,并将此图像的链接保存在数据库中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2011-09-24
    相关资源
    最近更新 更多