Node.js,将bin文件存储为BYTEA到pgsql(损坏的文件)

3

出于某种原因,我需要将一些文件(主要是图像或pdf文件)存储到我的数据库(PG 9.2.20)中。这些文件是由用户上传的,但当我下载它们时,它们会损坏。

  • 我正在使用nodejs。
  • 我存储文件的列类型是BYTEA。

这是我存储它们的方式:

const { files, fields } = await asyncBusboy(ctx.req);
const fileName = files[0].filename;
const mimeType = files[0].mimeType;
const bufferedFile = fs.readFileSync(files[0].path, { encoding: 'hex' });
const fileData = `\\x${bufferedFile}`;

//Just a basic insert into with knex.raw
const fileId = await storageModel.create(fields.name, fields.description, fileName, mimeType, fileData, ctx.user);

这是我检索文件的方式:
const file = await storageModel.find(ctx.params.fileId, ctx.user);
ctx.body = Buffer.from(file.file_bin, 'hex');
ctx.set('Content-disposition', `attachment; filename=${file.file_name}`);

文件已损坏,当我仔细查看时,上传的文件和我下载的文件是不同的。请参考十六进制截图,下载的文件在开头有一些额外的数据:http://imgur.com/a/kTRAB 经过更多测试,我发现问题出在koa部分,当我将缓冲区放入ctx.body中时,它被损坏了(?)。
编辑:我正在使用Swagger UI: https://github.com/swagger-api/swagger-ui/issues/1605

我正在使用Swagger客户端测试我的路由。当我通过在浏览器中调用URL进行测试时,它可以正常工作... - thesearentthedroids
1个回答

3
不应将bytea用作常规文本字符串。您应直接传递类型为Buffer的内容,并让驱动程序正确转义它。
不确定您使用的是哪个驱动程序,例如: - pg-promise会自动执行此操作,请参阅示例。 - node-postgres通常会自动执行此操作,但我知道数组存在问题,最近已被修复,请参见此处。 - massive.js基于pg-promise v3.0+,所以相同的操作都有效。

我认为knexjs正确地转义了缓冲区。我不确定,所以我继续搜索,用一个TEXT列替换我的BYTEA列。现在我使用.toString方法来存储我的缓冲区,然后当我检索数据时,我使用Buffer.from(都是在base 64中)重新创建缓冲区,然后返回它。我的文件仍然损坏(与我的屏幕截图中的偏移量相同)。 - thesearentthedroids
@thesearentthedroids 这是一个非常糟糕的方法。相反,你应该询问如何在knex中插入二进制数据,并将类型保持为bytea。我无法提供更多细节,因为我自己不熟悉knex。 - vitaly-t
@vitaly-t,所以明确一下,您建议将缓冲区保存在“text”PostgreSQL列中?Nodejs中的pbkdf2生成缓冲区,我想将其存储在PostgreSQL中。我在搜索周围时发现了您的答案。谢谢。 - slevin
1
@slevin 不,我从未建议过这样做。通常使用类型 bytea,并直接保存类型 Buffer,让库自动转义它。 - vitaly-t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接