[javascript] 파일을 업로드하기위한 fileReader.readAsBinaryString
fileReader.readAsBinaryString을 사용하여 AJAX를 통해 서버에 PNG 파일을 업로드하려고 시도하고 코드를 제거했습니다 (fileObject는 내 파일에 대한 정보를 포함하는 객체입니다).
var fileReader = new FileReader();
fileReader.onload = function(e) {
var xmlHttpRequest = new XMLHttpRequest();
//Some AJAX-y stuff - callbacks, handlers etc.
xmlHttpRequest.open("POST", '/pushfile', true);
var dashes = '--';
var boundary = 'aperturephotoupload';
var crlf = "\r\n";
//Post with the correct MIME type (If the OS can identify one)
if ( fileObject.type == '' ){
filetype = 'application/octet-stream';
} else {
filetype = fileObject.type;
}
//Build a HTTP request to post the file
var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(fileObject.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + e.target.result + crlf + dashes + boundary + dashes;
xmlHttpRequest.setRequestHeader("Content-Type", "multipart/form-data;boundary=" + boundary);
//Send the binary data
xmlHttpRequest.send(data);
}
fileReader.readAsBinaryString(fileObject);
업로드하기 전에 (VI 사용) 파일의 처음 몇 줄을 살펴보면
업로드 후 동일한 파일이 표시됩니다.
그래서 어딘가에 서식 / 인코딩 문제처럼 보였고, 원시 바이너리 데이터에서 간단한 UTF8 인코딩 기능을 사용해 보았습니다.
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;
)
그런 다음 원래 코드에서
//Build a HTTP request to post the file
var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(file.file.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + utf8encode(e.target.result) + crlf + dashes + boundary + dashes;
나에게 출력을 제공합니다
여전히 원시 파일이 무엇인지 = (
인코딩 문제를 피하기 위해 파일을 인코딩 /로드 / 처리하는 방법은 HTTP 요청에서 수신되는 파일이 업로드되기 전의 파일과 동일합니다.
다른 유용한 정보, fileReader.readAsBinaryString ()을 사용하는 대신 fileObject.getAsBinary ()를 사용하여 바이너리 데이터를 가져 오면 제대로 작동합니다. 그러나 getAsBinary는 Firefox에서만 작동합니다. 나는 Mac에서 Firefox와 Chrome에서 이것을 테스트했으며 둘 다 동일한 결과를 얻었습니다. 백엔드 업로드는 Mac에서 다시 실행 되는 NGINX 업로드 모듈에 의해 처리됩니다 . 서버와 클라이언트가 동일한 시스템에 있습니다. 내가 업로드하려는 모든 파일에서 똑같은 일이 발생합니다. 가장 분명한 예이기 때문에 PNG를 선택했습니다.
답변
을 사용 fileReader.readAsDataURL( fileObject )
하면 base64로 인코딩되어 서버에 안전하게 업로드 할 수 있습니다.
답변
(다음은 늦었지만 완전한 답변입니다)
FileReader 메서드 지원
FileReader.readAsBinaryString()
한다 추천하지 않습니다. 그것을 사용하지 마십시오! 더 이상 W3C 파일 API 작업 초안에 없습니다 .
void abort();
void readAsArrayBuffer(Blob blob);
void readAsText(Blob blob, optional DOMString encoding);
void readAsDataURL(Blob blob);
NB : File
이것은 일종의 확장 된 Blob
구조입니다.
Mozilla는 여전히 MDN FileApi 문서readAsBinaryString()
에서이를 구현 하고 설명합니다 .
void abort();
void readAsArrayBuffer(in Blob blob); Requires Gecko 7.0
void readAsBinaryString(in Blob blob);
void readAsDataURL(in Blob file);
void readAsText(in Blob blob, [optional] in DOMString encoding);
readAsBinaryString()
지원 중단 의 이유 는 다음과 같습니다. JavaScript 문자열의 표준은 DOMString
임의의 바이너리 데이터가 아닌 UTF-8 문자 만 허용한다는 것입니다. 따라서 readAsBinaryString ()을 사용하지 마십시오. 그것은 안전하지 않으며 ECMAScript를 전혀 준수하지 않습니다.
우리는 JavaScript 문자열이 바이너리 데이터를 저장해서는 안되지만 Mozilla는 어떤 종류의 데이터를 저장할 수 있다는 것을 알고 있습니다. 제 생각에는 위험합니다. Blob
그리고 typed arrays
( ArrayBuffer
아직 구현되지 않았지만 필요하지 않은 StringView
)는 한 가지 목적으로 발명되었습니다 : UTF-8 문자열 제한없이 순수한 바이너리 데이터를 사용할 수 있도록합니다.
XMLHttpRequest 업로드 지원
XMLHttpRequest.send()
다음과 같은 호출 옵션이 있습니다.
void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);
XMLHttpRequest.sendAsBinary()
다음과 같은 호출 옵션이 있습니다.
void sendAsBinary( in DOMString body );
sendAsBinary ()는 표준이 아니며 Chrome에서 지원되지 않을 수 있습니다.
솔루션
따라서 몇 가지 옵션이 있습니다.
send()
FileReader.result
의FileReader.readAsArrayBuffer ( fileObject )
. 조작하는 것이 더 복잡하지만 (별도의 send ()를 만들어야 함) RECOMMENDED APPROACH 입니다.send()
FileReader.result
의FileReader.readAsDataURL( fileObject )
. 쓸모없는 오버 헤드와 압축 대기 시간을 생성하고 서버 측에서 압축 해제 단계가 필요하지만 Javascript에서 문자열로 조작하기 쉽습니다.- 가되는 비표준 및 의
sendAsBinary()
FileReader.result
FileReader.readAsBinaryString( fileObject )
MDN은 다음과 같이 말합니다.
바이너리 콘텐츠를 전송하는 가장 좋은 방법 (파일 업로드 등)은 send () 메서드와 함께 ArrayBuffers 또는 Blob을 사용하는 것입니다. 그러나 문자열 화 가능한 원시 데이터를 보내려면 대신 sendAsBinary () 메서드를 사용하거나 StringView (기본이 아닌) 유형의 배열 수퍼 클래스를 사용하십시오.
답변
이를 지원하는 브라우저에서 가장 좋은 방법은 파일을 Blob으로 보내거나 멀티 파트 양식을 원하는 경우 FormData를 사용하는 것입니다. 이를 위해 FileReader가 필요하지 않습니다. 이것은 데이터를 읽는 것보다 더 간단하고 효율적입니다.
특별히로 보내려면 multipart/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);
을 사용하는 대신 데이터를 직접 보낼 수도 있습니다 multipart/form-data
. 설명서를 참조하십시오 . 물론 이것은 서버 측 변경도 필요합니다.
// 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);
브라우저 지원은 http://caniuse.com/#feat=xhr2(IE 10 이상을 포함한 대부분의 브라우저)를 참조하십시오 .