【问题标题】:reading a file in js is corupting the file在js中读取文件会损坏文件
【发布时间】:2020-11-21 10:42:23
【问题描述】:

在 js 中我正在运行这段代码

let str = new TextDecoder("utf8").decode(new Uint8Array(reader.result));

let data = {
    name:file.name,
    size: args.loaded,
    contentsize:str.length,
    type:file.type,
    content:str
};
let res = await $.post({
    url:"/api/files",
    data:JSON.stringify(data),
    processData: false,
    contentType: "application/json",
})

reader.result 是

的输出
reader.readAsArrayBuffer(file);

然后在 php 中提取

$new["actual"] =strlen($new["content"]);
$new["content"] = new MongoDB\BSON\Binary($new["content"] ,MongoDB\BSON\Binary::TYPE_GENERIC);
$result = IO::$db->files->insertOne($new);

然后生成一个 db 文档

{ 
    "name" : "test.pdf", 
    "size" : NumberInt(128454), 
    "contentsize" : NumberInt(122693), 
    "type" : "application/pdf", 
    "actual" : NumberInt(215693)
}

但是,当我将文件的内容移回文件系统时,文件已损坏并且无法打开。 我已经运行了 VSCode 附带的文件比较器,并说 DB 内容和原始内容之间存在 0 差异,所以我只能认为问题在于文件大小和读取内容的 3kb 差异,但是什么或者为什么逃脱我

注意似乎只是二进制文件

【问题讨论】:

    标签: javascript php ajax pdf


    【解决方案1】:

    您的示例是一个 PDF 文件。 PDF 文件不是文本文件,不应作为文本文件处理。如果更改行尾,这将更改文件中不同对象的偏移量,这将损坏 PDF 文件。更糟糕的是,如果 PDF 文件中有二进制流(例如字体、图像等),它会破坏流的内容,并可能导致无法对其进行解码。

    要解决此问题,请确保将 PDF 文件作为二进制文件进行读写。

    【讨论】:

    • 也许你可以解释一下
    • 我刚做了。我不写 PHP,但我确信有很多关于如何在 PHP 中读写文件二进制文件的文档。
    • 所以我正在将二进制流读入字节数组,指示 javascript 它可以使用 UTF8 编码将字节数组解释为字符串,然后我通过 http 传递二进制数据到php,它接收二进制输入流并将其解码为二进制字符串,然后将其保存到数据库中,这是一个二进制字段,因为它从头到尾都是二进制数据,究竟哪一部分需要更多二进制
    【解决方案2】:

    好的,UTF-8 规范不包括字节数据范围内所有位码的字符,其他语言(例如 PHP)通过添加完成字节码映射的特殊非 UTF-8 字符来解决这个问题,但这是在 JavaScript 中不是这样

    所以这是 JavaScript 的一个限制,它不会告诉你它已经命中了一个字节码,它不能反序列化,这会突出一个问题已经发生,它只是跳过那个字节,然后移动到下一个,损坏您的数据并隐藏发生损坏的原因。

    这意味着您不能在 JavaScript 中使用 UTF-8 编码器来编码任何包含不受支持的字节码之一的内容,要绕过这个选项,您可以将字节转换为 HEX 字符串,然后使用它要在服务器端反序列化,这会导致一定程度的数据膨胀,因为您使用 2 个字节来发送一个字节(尽管这比尝试对字节数组进行编码要少得多)但是作为 2 个字母的十六进制字符串映射所有字节范围值意味着二进制数据没有损坏,并且可以安全地用于基于文本的数据序列化,如通过 JavaScript 实现的 JSON

    【讨论】:

    • 你让这听起来像是 Javascript 的缺陷。实际的错误在于假装一些任意二进制是 UTF-8 编码的文本并首先应用 UTF-8 解码器。 (但严格来说,它不应该跳过字节,它不能解释为 UTF-8 编码的字符数据,它应该返回一个替换字符 �。)
    • 我会说不报告错误是一个缺陷,如果它报告它遇到了一个无法解码的错误位代码,我就会知道有一个问题以及那个问题是什么,但是,如果它像您建议的那样使用替换字符,那么它的工作方式与支持二进制字符串数据的其他语言(如 PHP)和 UTF-8 解码器的工作方式相同,无论哪种方式,这都是语言的明确限制
    • 这(认真地)回到我的答案 - 不要将 PDF 视为文本,因为它不是。 UTF-8 是一种文本编码 - PDF 文件是二进制的。这两件事不应该混为一谈。你可能不喜欢这个答案,但它仍然是正确的。
    • 但是你不会解释你的意思你只是给出了一个没有细节和预期知识的高级答案,正如我在给你的回复中所说,我完全在二进制中工作,所以回答“更加二进制”与“js 中的 UTF8 不支持所有二进制数据,因此不能与二进制值一起使用”不同,一个是任意陈述,不能解释问题,另一个是解释不给予理解的答案不是答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 2016-02-05
    • 1970-01-01
    相关资源
    最近更新 更多