我正在尝试通过HTML5 FileReader在Web浏览器中选择本地JPEG文件,因此我可以将其提交到服务器而无需重新加载页面。所有的机制都在工作,我想我正在传输和保存JavaScript给我的确切数据,但结果是服务器上的JPEG文件无效。以下是演示此问题的基本代码:
<form name="add_photos">
<input type="file" name="photo" id="photo" /><br />
<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并尝试在预览中打开它,预览说文件“可能已损坏或使用预览无法识别的文件格式。”
如果我打开桌面上的原始文件和文本编辑器中服务器上的上传文件来检查它们的内容,它们几乎可以完全相同。原始文件的开头如下:
ˇÿˇ‡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(文件),图像将被正确传输并保存在服务器上。所以我的问题基本上解决了,但是我会给那些能解释为什么我的原始方法与readAsBinaryString不起作用的人奖励答案。
答案 0 :(得分:4)
你的问题在于readAsBinaryString
。这会将二进制数据逐字节传输到字符串中,以便您将文本字符串发送到PHP文件。现在,文本字符串始终具有编码;当您使用XmlHttpRequest上传字符串by default it will use UTF-8时。
因此,每个原本应该代表一个字节的字符将被编码为UTF-8 ...对于每个字符使用多个字节,代码点大于127!
最好的方法是使用readAsArrayBuffer
代替readAsBinaryString
。这将避免所有字符集转换(在dealing with strings时必需)。