Javascript 用于上载文件的fileReader.readAsBinaryString
尝试使用fileReader.readAsBinaryString通过AJAX将PNG文件上载到服务器,简化代码(fileObject是包含我文件信息的对象) 在上传(使用VI)之前检查文件的前几行可以让我 上传后显示相同的文件 所以它看起来像是某个地方的格式化/编码问题,我尝试对原始二进制数据使用一个简单的UTF8编码函数Javascript 用于上载文件的fileReader.readAsBinaryString,javascript,encoding,upload,filereader,Javascript,Encoding,Upload,Filereader,尝试使用fileReader.readAsBinaryString通过AJAX将PNG文件上载到服务器,简化代码(fileObject是包含我文件信息的对象) 在上传(使用VI)之前检查文件的前几行可以让我 上传后显示相同的文件 所以它看起来像是某个地方的格式化/编码问题,我尝试对原始二进制数据使用一个简单的UTF8编码函数 function utf8encode(string) { string = string.replace(/\r\n/g,"\n");
function utf8encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
)
这给了我
仍然不是原始文件的样子=(
如何对文件进行编码/加载/处理以避免编码问题,从而使HTTP请求中接收的文件与上载前的文件相同
如果不使用fileReader.readAsBinaryString()而使用fileObject.getAsBinary()的话,还有一些其他可能有用的信息为了获得二进制数据,它工作得很好。但是getAsBinary只在Firefox中工作。我已经在Firefox和Chrome中进行了测试,都在Mac上,得到了相同的结果。后端上传由处理,同样在Mac上运行。服务器和客户端在同一台机器上。我尝试上传的任何文件都会发生同样的事情,I just选择PNG是因为它是最明显的例子。使用
文件阅读器。readAsDataURL(fileObject)
,这将把它编码到base64,你可以安全地上传到你的服务器。(下面是一个很晚但完整的答案)
文件读取器方法支持
FileReader.readAsBinaryString()
已弃用。不要使用它!它不再位于:
注意:File
是一种扩展的Blob
结构
Mozilla仍然实现了readAsBinaryString()
,并在以下内容中进行了描述:
我认为,readAsBinaryString()
弃用的原因如下:JavaScript字符串的标准是DOMString
,它只接受UTF-8字符,而不接受随机二进制数据。因此不要使用readAsBinaryString(),这既不安全,也不符合ECMAScript
我们知道JavaScript字符串不应该存储二进制数据,但Mozilla在某种程度上可以。在我看来,这是危险的。Blob
和类型化数组
(ArrayBuffer
和尚未实现但不必要的StringView
)它们的发明有一个目的:允许使用纯二进制数据,而不受UTF-8字符串的限制
XMLHttpRequest上传支持
具有以下调用选项:
void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);
void sendAsBinary( in DOMString body );
具有以下调用选项:
void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);
void sendAsBinary( in DOMString body );
sendAsBinary()不是标准,Chrome可能不支持它
解决
所以你有几个选择:
send()
文件阅读器的FileReader.readAsArrayBuffer(fileObject)
的FileReader.result
。操作起来更复杂(您必须为其单独发送()),但这是推荐的方法send()
FileReader.readAsDataURL(fileObject)的FileReader.result
。它会产生无用的开销和压缩延迟,需要在服务器端执行解压缩步骤,但很容易在Javascript中作为字符串进行操作sendAsBinary()
文件读取器的FileReader.result
文件读取器.readAsBinaryString(fileObject)在支持它的浏览器中,最好的方法是将文件作为Blob发送,或者如果需要多部分表单,则使用FormData。这不需要文件读取器。这比尝试读取数据更简单、更高效 如果您特别希望将其作为
多部分/form data
发送,可以使用FormData对象:
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", '/pushfile', true);
var formData = new FormData();
// This should automatically set the file name and type.
formData.append("file", file);
// Sending FormData automatically sets the Content-Type header to multipart/form-data
xmlHttpRequest.send(formData);
您也可以直接发送数据,而不是使用多部分/表单数据
。请参阅。当然,这也需要服务器端更改
// file is an instance of File, e.g. from a file input.
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", '/pushfile', true);
xmlHttpRequest.setRequestHeader("Content-Type", file.type);
// Send the binary data.
// Since a File is a Blob, we can send it directly.
xmlHttpRequest.send(file);
有关浏览器支持,请参阅:(大多数浏览器,包括IE 10+。在正常工作时,保存在服务器上的文件版本是Base64编码的(应该是这样)。是否无法将其作为二进制数据传输,而不是Base64编码的(即,好像是使用正常的
字段上载的)如果服务器上有PHP,则可以在存储(文件)之前对其进行base64_解码。没有-没有安全的方法通过http传输原始二进制数据。使用readAsDataURL可以在服务器上实现这一点,通过PHP的base64_解码将其运行回来(我们实际上使用的是Python,但PHP是一个很好的测试)我得到的仍然不是原始的二进制数据,也不是有效的映像=(@O,我的坏!在服务器上,您必须将base64字符串除以“,”并且只存储第二部分-这样mime类型将不会与实际文件内容一起存储。不,这是不高效的。这将增加文件大小137%,并造成服务器开销。但是没有其他方法支持F***IEI很抱歉再次挖掘此内容,只想添加这可能是发送二进制数据(等PDF文件)的最简单方法通过FileReader.readAsDataURL
和onload
处理程序,而不是仅仅发送event.target.result
(这不是干净的base64编码字符串),首先使用一些类似于event.target.result=event.target.result.match(/,(.*)/)的正则表达式来清理它[1]
并将真实的base64发送到服务器进行解码。由于任何人都可以编辑MDN,我可能不会将其用作源代码。@user1299518,最好使用event.target.result.split(“,”),2)[1]
,而不是match
@kriWebdev:在建议的选项中,您提到需要单独发送()。为什么?建议的方法对
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", '/pushfile', true);
var formData = new FormData();
// This should automatically set the file name and type.
formData.append("file", file);
// Sending FormData automatically sets the Content-Type header to multipart/form-data
xmlHttpRequest.send(formData);
// file is an instance of File, e.g. from a file input.
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", '/pushfile', true);
xmlHttpRequest.setRequestHeader("Content-Type", file.type);
// Send the binary data.
// Since a File is a Blob, we can send it directly.
xmlHttpRequest.send(file);