JavaScript:为什么 `FileReader.readAsBinaryString()` 会破坏结果

JavaScript: Why `FileReader.readAsBinaryString()` corrupts result

我有一个文件输入。在 change 事件中,我将指定文件读取到 post JSON 对象中的数据到 API.

function changeHandler( event ) {
    const fileReader = new FileReader();
    fileReader.addEventListener(
        'loadend',
        function ( event )
        {
            console.log( CryptoJS.MD5( event.originalTarget.result ).toString() );
            /** ... */
        }
    );
    fileReader.readAsBinaryString( event.originalTarget.files[ 0 ] );
}

在我的测试中,我尝试阅读 composer.phar。它指出 MD5 校验和不是真正的校验和。所以很明显 FileReader 没有正确读取文件。任何假设会发生什么?也许 FileReader 使用了一些编码?

阐明我的需求

当我将数据发送到 REST API 时,multipart/form-data 没有请求。因此我不能使用 PHP 的 $_FILES 服务器端。

我需要在请求正文中的内容类型为 application/json 的 JSON 对象中发送文件。因此我需要在客户端手动读取文件并将其存储在服务器端。目前无法保证客户端数据,因为读取数据的 MD5 校验和与所选二进制文件的真实 MD5 校验和不匹配。

示例请求正文

{
    "id": "d0f11715-c0b1-4a1d-b471-4408c78fbe01",
    "data": "This is some JSON encoded string of possibly binary file data."
}

更新

我声明读取的数据长度与原始文件大小完全一致

更新

此问题已被标记为重复,但上述回答并未解决我的问题。我尝试了提到的两个例子。

bashcmdmd5sum

计算出的MD5校验和
56f13c034e5e0c58de35b77cbd0f1b0b  resources/composer.phar
function changeHandler( event ) {
    const fileReader = new FileReader();
    fileReader.addEventListener(
        'loadend',
        function ( event )
        {
            console.log( CryptoJS.MD5( event.target.result ).toString() );
        }
    );
    fileReader.readAsBinaryString( event.target.files[ 0 ] );
}

// outputs 784102b153672149418605c1d4abcc3c
function changeHandler( event ) {
    const fileReader = new FileReader();
    fileReader.addEventListener(
        'loadend',
        function ( event )
        {
            const wordArray = CryptoJS.lib.WordArray.create( event.target.result );
            console.log( CryptoJS.MD5( wordArray ).toString() );
        }
    );
    fileReader.readAsArrayBuffer( event.target.files[ 0 ] );
}

// outputs 231bc133db6bdf3f665b53b0d2f631d1

我更改了@kaiido 提到的使用的库。
https://github.com/satazor/js-spark-md5

function changeHandler( event )
        {
            const fileReader = new FileReader();
            fileReader.addEventListener(
                'loadend',
                function ( event )
                {
                    const arrayBuffer = new SparkMD5.ArrayBuffer();
                    arrayBuffer.append( event.target.result );
                    console.log( arrayBuffer.end() );

                    base64Encoded = btoa(
                        [].reduce.call(
                            new Uint8Array( event.target.result ),
                            function ( p, c )
                            {
                                return p + String.fromCharCode( c )
                            },
                            ''
                        )
                    );
                }
            );
            fileReader.readAsArrayBuffer( event.target.files[ 0 ] );
        }

所以虽然现在很明显读取的数据是正确的,但我只需要处理读取的数据。 Base64解码值服务器端的校验和现在也正确,建议使用FileReader.readAsArrayBuffer()