5

我正在尝试通过 HTML5 FileReader 在 Web 浏览器中选择一个本地 JPEG 文件,这样我就可以将其提交到服务器而无需重新加载页面。所有机制都在工作,我想我正在传输和保存 JavaScript 给我的确切数据,但结果是服务器上的 JPEG 文件无效。这是演示该问题的基本代码:

<form name="add_photos">
    ​&lt;input type=​"file" name=​"photo" id=​"photo" /><br />
    ​&lt;input type=​"button" value=​"Upload" onclick=​"upload_photo()​;​" />​
</form>

<script type="text/javascript">
    function upload_photo() {
        file = document.add_photos.photo.files[0];
        if (file) {
            fileReader = new FileReader();
            fileReader.onload = upload_photo_ready;
            fileReader.readAsBinaryString(file);
        }
    }

    function upload_photo_ready(event) {
        data = event.target.result;
        // alert(data);

        URL = "submit.php";
        ajax = new XMLHttpRequest();
        ajax.open("POST", URL, 1);
        ajax.setRequestHeader("Ajax-Request", "1");
        ajax.send(data);
    }
</script>

然后我的 PHP 脚本执行此操作:

$data = file_get_contents("php://input");
$filename = "test.jpg";
file_put_contents($filename, $data);
$result = imagecreatefromjpeg($filename);

最后一行抛出 PHP 错误“test.jpg 不是有效的 JPEG 文件”。如果我将数据下载回我的 Mac 并尝试在 Preview 中打开它,Preview 会说文件“可能已损坏或使用了 Preview 无法识别的文件格式”。

如果我在文本编辑器中打开桌面上的原始文件和服务器上上传的文件以检查它们的内容,它们几乎但不完全相同。原始文件的开头是这样的:

ˇÿˇ‡JFIFˇ˛;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90

但是上传的文件是这样开始的:

ÿØÿàJFIFÿþ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90

有趣的是,如果我在上面注释掉的行中查看 JavaScript 警报中的数据,它看起来就像上传文件的数据,所以看起来 FileReader 在一开始就没有提供正确的数据,而不是在服务器上传输或保存数据时引入的问题。谁能解释一下?

我正在使用 Safari 6,我也尝试过 Firefox 14。

更新:我刚刚发现,如果我跳过 FileReader 代码并将 ajax.send(data) 更改为 ajax.send(file),图像就会正确传输并保存在服务器上。所以我的问题基本解决了,但是我会将答案点奖励给任何可以解释为什么我使用 readAsBinaryString 的原始方法不起作用的人。

4

1 回答 1

5

你的问题在于readAsBinaryString。这会将二进制数据逐字节传输到字符串中,以便您将文本字符串发送到您的 PHP 文件。现在一个文本字符串总是有一个编码;当您使用 XmlHttpRequest 上传字符串时,默认情况下它将使用 UTF-8

因此,原本应该代表一个字节的每个字符都将被编码为 UTF-8 ......它为每个字符使用多个字节,代码点高于 127!

Your best best is to use readAsArrayBuffer instead of readAsBinaryString. This will avoid all the character set conversions (that are necessary when dealing with strings).

于 2013-03-22T12:34:29.680 回答