JS - TEXT 文件 GZIP'ed 上传(修复:错误的回调)
JS - TEXT File GZIP'ed for UPLOAD (fixed: wrong callback)
浏览文件、上传和 GZIP 压缩都可以正常工作,但 GZIP 压缩后的 NewFile
会被忽略并发送原始文件 [i]。
我没有将文件 [i] 对象传递给 Upload()
,而是使用 GZIP 压缩后的数据创建了一个新的 File object
,然后将其传递给 Upload()
,这就是“ <<< HERE <<<" 在代码下方注释:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
</head>
<body>
<p>Send new/updated text to the server:</p>
<form id="upload" action="/?entity" method="POST"
enctype="multipart/form-data">
<input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="3000000" />
<div>
<input type="file" id="fileselect" name="fileselect[]" multiple="multiple" />
<div id="filedrag">Drop your TEXT<br>file(s) here!</div>
</div>
<div id="submitbutton">
<button type="submit">Upload Files</button>
</div>
</form>
<table><tr><td>
<fieldset><legend>Server Reply</legend><div id="srvreply"></div></fieldset>
</td><td>
<fieldset><legend>Network Transfer</legend><div id="progress"></div></fieldset>
</td><td>
<fieldset><legend>Dropped Files</legend><div id="doclist"><p></p></div></fieldset>
</td></tr></table>
<script src="https://raw.githubusercontent.com/imaya/zlib.js/master/bin/zlib_and_gzip.dev.min.js"></script>
<script>
// -----------------------------------------------------------------------------
function $id(id) {return document.getElementById(id)}
// -----------------------------------------------------------------------------
function Output(msg)
{var m = $id("doclist"); m.style.visibility="visible";
m.innerHTML += msg; m.scrollTop = m.scrollHeight;
}
// -----------------------------------------------------------------------------
function toUTF8Array(str) { // JS strings are UTF-16 (bloated)
var utf8 = [];
for(var i=0; i<str.length; i++)
{var charcode = str.charCodeAt(i);
if(charcode < 0x80) utf8.push(charcode);
else
if(charcode < 0x800)
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
else
if(charcode < 0xd800 || charcode >= 0xe000)
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
else // surrogate pair
{ i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff))
utf8.push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
// =============================================================================
// Drag & Drop, UI, JPG & TEXT files
// -----------------------------------------------------------------------------
(function(){
// -----------------------------------------------------------------------------
function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));}
// -----------------------------------------------------------------------------
// Loop to process all files
// -----------------------------------------------------------------------------
function FileDragHover(e)
{e.stopPropagation();
e.preventDefault();
e.target.className = (e.type == "dragover" ? "hover" : "");
}
function FileSelectHandler(e)
{FileDragHover(e); // cancel event and hover styling
var files = e.target.files || e.dataTransfer.files; // fetch FileList
for(var i = 0; f = files[i]; i++) // process and upload all files
UploadFile(ParseFile(f)); // <<<<<<<<<< HERE <<<<<<<<<<
}
// -----------------------------------------------------------------------------
// Read Dropped Files, Output File Name and Size
// -----------------------------------------------------------------------------
function ParseFile(file)
{ var newFile = file;
if(!file.type.indexOf("text")) // "text/plain"
{ var reader = new FileReader();
reader.onload = function(e)
{ Output(file.name + " "
+ Math.round((file.size/1024) * 100) / 100 + " KB<br>");
// compress payload with GZIP
var gzip = new Zlib.Gzip(file);
var comp = gzip.compress();
Output("read "
+ Math.round((file.size/1024) * 100) / 100
+ " KB, comp "
+ + Math.round((comp.length/1024) * 100) / 100
+ " KB<br>");
newFile = new File([new Uint8Array(comp)], file.name,
{type:'text/plain'});
}
reader.readAsText(file);
return newFile;
}
}
// -----------------------------------------------------------------------------
// Send Files to Server
// -----------------------------------------------------------------------------
function UploadFile(file)
{ // location.host
var xhr = new XMLHttpRequest();/*
Output("xhr.upload: " + xhr.upload + "<br>file.type: " + file.type
+ "<br>file.size: " + file.size + "<br>");*/
if(xhr.upload
&& (file.type == "text/plain" || file.type == "image/jpeg"
|| file.type.indexOf("ms-excel") > 0
|| file.type.indexOf("spreadsheet") > 0)
&& file.size <= $id("MAX_FILE_SIZE").value)
{ // create progress bar
var o = $id("progress");
var progress = o.appendChild(document.createElement("p"));
progress.appendChild(document.createTextNode(file.name + ": 0%"));
o.scrollTop = o.scrollHeight;
xhr.upload.addEventListener("progress", function(e) // progress bar
{ var pc = parseInt(e.loaded / e.total * 100);
var txt = progress.innerHTML;
progress.innerHTML = txt.slice(0, txt.indexOf(":") + 2) + pc + "%";
}, false);
// file received/failed
// 0: request not initialized
// 1: server connection established
// 2: request received
// 3: processing request
// 4: request finished and response is ready
xhr.onreadystatechange = function(e) {
if(xhr.readyState == 0)
$id("srvreply").innerHTML += "<br>- preparing request";
if(xhr.readyState == 1)
$id("srvreply").innerHTML += "<br>- server connected";
if(xhr.readyState == 2)
$id("srvreply").innerHTML += "<br>- server got request";
if(xhr.readyState == 3)
$id("srvreply").innerHTML += "<br>- server processing request";
if(xhr.readyState == 4)
{
// 200: "OK", 403: "Forbidden", 404: "Not Found"
var msg = (xhr.status == 200 ? "success" : "failure");
progress.className = msg;
//$id("srvreply").innerHTML += "<br>- " + xhr.status + " "
// + xhr.statusText;
if(xhr.status == 200)
$id("srvreply").innerHTML += "<br>" + xhr.responseText;
// force scrolling-down (so users see the latest entries)
$id("srvreply").scrollTop = $id("srvreply").scrollHeight;
}
};
xhr.open("POST", $id("upload").action, true); // start upload
xhr.overrideMimeType('text/plain; charset=utf-8');
xhr.setRequestHeader("XXX-FILENAME", file.name);
xhr.send(file);
}
}
// -----------------------------------------------------------------------------
function Init()
{ var fileselect = $id("fileselect"), filedrag = $id("filedrag"),
submitbutton = $id("submitbutton");
fileselect.addEventListener("change", FileSelectHandler, false);
var xhr = new XMLHttpRequest(); // is XHR2 available?
if(xhr.upload) // file drop
{ filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
submitbutton.style.display = "none"; // remove submit button
}
}
// -----------------------------------------------------------------------------
if(window.File && window.FileList && window.FileReader) { Init(); }
// -----------------------------------------------------------------------------
})();
// -----------------------------------------------------------------------------
</script>
</body>
</html>
但是,Upload() 发送的是原始文件[i] 对象,而不是我新创建的对象。我当然遗漏了一些明显的东西,但我看不到什么。
完整的 HTML/JS 代码已发布,以便人们可以在家进行测试。
GZIP 负载为空,因为源文件在 readAsText(file)
之后尚未加载:
输出:
- 阅读前:EMPTY
- 阅读后:正在加载
- 加载结束:完成 <<<<<<
onload[END]
qcm.txt 2.99 KB(读取 2.99 KB,压缩 0.8 KB)<<<<<< 可信压缩
工作代码:
var rdSt = {};
rdSt[FileReader.EMPTY] = 'EMPTY';
rdSt[FileReader.LOADING] = 'LOADING';
rdSt[FileReader.DONE] = 'DONE';
function ParseFile(file)
{
if(!file.type.indexOf("text")) // "text/plain"
{ var reader = new FileReader();
reader.onloadend = function(e)
{ var data = e.target.result;
var gzip = new Zlib.Gzip(data);
var comp = gzip.compress();
var newFile = new File([new Uint8Array(comp)], file.name,
{type:'text/plain'});
Output('- onloadend : '+rdSt[reader.readyState]+"<br>");
Output(file.name +" "+ Math.round((file.size/1024)*100)/100
+ " KB<br>"
+ "(read " + Math.round((file.size/1024)*100)/100
+ " KB, comp "
+ Math.round((comp.length/1024)*100)/100 +" KB)<br>");
UploadFile(newFile); // <<<<< MUST be done HERE!
}
Output('- before read: '+rdSt[reader.readyState]+"<br>");
reader.readAsText(file);
Output('- after read : '+rdSt[reader.readyState]+"<br>");
}
}
所以回调是强制性的 - 我只是没有合适的回调(onload
而不是 onloadend
)。
显然,newFile
始终未压缩,因为压缩甚至没有开始! ParseFile()
不能 return newFile
因为压缩仅以 onloadend()
结束(回调现在调用 UploadFile()
)。
作为最新练习,zlib.js "Gzip" 压缩不符合 HTTP GZIP 标准(或者我误用了另一个 JS 库)。
https://www.javascripture.com/ 帮我找到了相关的 Javascript 文档(稀缺资源)。
运气好的话,这种痛苦的辛苦工作会帮助别人...
浏览文件、上传和 GZIP 压缩都可以正常工作,但 GZIP 压缩后的 NewFile
会被忽略并发送原始文件 [i]。
我没有将文件 [i] 对象传递给 Upload()
,而是使用 GZIP 压缩后的数据创建了一个新的 File object
,然后将其传递给 Upload()
,这就是“ <<< HERE <<<" 在代码下方注释:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
</head>
<body>
<p>Send new/updated text to the server:</p>
<form id="upload" action="/?entity" method="POST"
enctype="multipart/form-data">
<input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="3000000" />
<div>
<input type="file" id="fileselect" name="fileselect[]" multiple="multiple" />
<div id="filedrag">Drop your TEXT<br>file(s) here!</div>
</div>
<div id="submitbutton">
<button type="submit">Upload Files</button>
</div>
</form>
<table><tr><td>
<fieldset><legend>Server Reply</legend><div id="srvreply"></div></fieldset>
</td><td>
<fieldset><legend>Network Transfer</legend><div id="progress"></div></fieldset>
</td><td>
<fieldset><legend>Dropped Files</legend><div id="doclist"><p></p></div></fieldset>
</td></tr></table>
<script src="https://raw.githubusercontent.com/imaya/zlib.js/master/bin/zlib_and_gzip.dev.min.js"></script>
<script>
// -----------------------------------------------------------------------------
function $id(id) {return document.getElementById(id)}
// -----------------------------------------------------------------------------
function Output(msg)
{var m = $id("doclist"); m.style.visibility="visible";
m.innerHTML += msg; m.scrollTop = m.scrollHeight;
}
// -----------------------------------------------------------------------------
function toUTF8Array(str) { // JS strings are UTF-16 (bloated)
var utf8 = [];
for(var i=0; i<str.length; i++)
{var charcode = str.charCodeAt(i);
if(charcode < 0x80) utf8.push(charcode);
else
if(charcode < 0x800)
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
else
if(charcode < 0xd800 || charcode >= 0xe000)
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
else // surrogate pair
{ i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff))
utf8.push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
// =============================================================================
// Drag & Drop, UI, JPG & TEXT files
// -----------------------------------------------------------------------------
(function(){
// -----------------------------------------------------------------------------
function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));}
// -----------------------------------------------------------------------------
// Loop to process all files
// -----------------------------------------------------------------------------
function FileDragHover(e)
{e.stopPropagation();
e.preventDefault();
e.target.className = (e.type == "dragover" ? "hover" : "");
}
function FileSelectHandler(e)
{FileDragHover(e); // cancel event and hover styling
var files = e.target.files || e.dataTransfer.files; // fetch FileList
for(var i = 0; f = files[i]; i++) // process and upload all files
UploadFile(ParseFile(f)); // <<<<<<<<<< HERE <<<<<<<<<<
}
// -----------------------------------------------------------------------------
// Read Dropped Files, Output File Name and Size
// -----------------------------------------------------------------------------
function ParseFile(file)
{ var newFile = file;
if(!file.type.indexOf("text")) // "text/plain"
{ var reader = new FileReader();
reader.onload = function(e)
{ Output(file.name + " "
+ Math.round((file.size/1024) * 100) / 100 + " KB<br>");
// compress payload with GZIP
var gzip = new Zlib.Gzip(file);
var comp = gzip.compress();
Output("read "
+ Math.round((file.size/1024) * 100) / 100
+ " KB, comp "
+ + Math.round((comp.length/1024) * 100) / 100
+ " KB<br>");
newFile = new File([new Uint8Array(comp)], file.name,
{type:'text/plain'});
}
reader.readAsText(file);
return newFile;
}
}
// -----------------------------------------------------------------------------
// Send Files to Server
// -----------------------------------------------------------------------------
function UploadFile(file)
{ // location.host
var xhr = new XMLHttpRequest();/*
Output("xhr.upload: " + xhr.upload + "<br>file.type: " + file.type
+ "<br>file.size: " + file.size + "<br>");*/
if(xhr.upload
&& (file.type == "text/plain" || file.type == "image/jpeg"
|| file.type.indexOf("ms-excel") > 0
|| file.type.indexOf("spreadsheet") > 0)
&& file.size <= $id("MAX_FILE_SIZE").value)
{ // create progress bar
var o = $id("progress");
var progress = o.appendChild(document.createElement("p"));
progress.appendChild(document.createTextNode(file.name + ": 0%"));
o.scrollTop = o.scrollHeight;
xhr.upload.addEventListener("progress", function(e) // progress bar
{ var pc = parseInt(e.loaded / e.total * 100);
var txt = progress.innerHTML;
progress.innerHTML = txt.slice(0, txt.indexOf(":") + 2) + pc + "%";
}, false);
// file received/failed
// 0: request not initialized
// 1: server connection established
// 2: request received
// 3: processing request
// 4: request finished and response is ready
xhr.onreadystatechange = function(e) {
if(xhr.readyState == 0)
$id("srvreply").innerHTML += "<br>- preparing request";
if(xhr.readyState == 1)
$id("srvreply").innerHTML += "<br>- server connected";
if(xhr.readyState == 2)
$id("srvreply").innerHTML += "<br>- server got request";
if(xhr.readyState == 3)
$id("srvreply").innerHTML += "<br>- server processing request";
if(xhr.readyState == 4)
{
// 200: "OK", 403: "Forbidden", 404: "Not Found"
var msg = (xhr.status == 200 ? "success" : "failure");
progress.className = msg;
//$id("srvreply").innerHTML += "<br>- " + xhr.status + " "
// + xhr.statusText;
if(xhr.status == 200)
$id("srvreply").innerHTML += "<br>" + xhr.responseText;
// force scrolling-down (so users see the latest entries)
$id("srvreply").scrollTop = $id("srvreply").scrollHeight;
}
};
xhr.open("POST", $id("upload").action, true); // start upload
xhr.overrideMimeType('text/plain; charset=utf-8');
xhr.setRequestHeader("XXX-FILENAME", file.name);
xhr.send(file);
}
}
// -----------------------------------------------------------------------------
function Init()
{ var fileselect = $id("fileselect"), filedrag = $id("filedrag"),
submitbutton = $id("submitbutton");
fileselect.addEventListener("change", FileSelectHandler, false);
var xhr = new XMLHttpRequest(); // is XHR2 available?
if(xhr.upload) // file drop
{ filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
submitbutton.style.display = "none"; // remove submit button
}
}
// -----------------------------------------------------------------------------
if(window.File && window.FileList && window.FileReader) { Init(); }
// -----------------------------------------------------------------------------
})();
// -----------------------------------------------------------------------------
</script>
</body>
</html>
但是,Upload() 发送的是原始文件[i] 对象,而不是我新创建的对象。我当然遗漏了一些明显的东西,但我看不到什么。
完整的 HTML/JS 代码已发布,以便人们可以在家进行测试。
GZIP 负载为空,因为源文件在 readAsText(file)
之后尚未加载:
输出:
- 阅读前:EMPTY
- 阅读后:正在加载
- 加载结束:完成 <<<<<<
onload[END]
qcm.txt 2.99 KB(读取 2.99 KB,压缩 0.8 KB)<<<<<< 可信压缩
工作代码:
var rdSt = {};
rdSt[FileReader.EMPTY] = 'EMPTY';
rdSt[FileReader.LOADING] = 'LOADING';
rdSt[FileReader.DONE] = 'DONE';
function ParseFile(file)
{
if(!file.type.indexOf("text")) // "text/plain"
{ var reader = new FileReader();
reader.onloadend = function(e)
{ var data = e.target.result;
var gzip = new Zlib.Gzip(data);
var comp = gzip.compress();
var newFile = new File([new Uint8Array(comp)], file.name,
{type:'text/plain'});
Output('- onloadend : '+rdSt[reader.readyState]+"<br>");
Output(file.name +" "+ Math.round((file.size/1024)*100)/100
+ " KB<br>"
+ "(read " + Math.round((file.size/1024)*100)/100
+ " KB, comp "
+ Math.round((comp.length/1024)*100)/100 +" KB)<br>");
UploadFile(newFile); // <<<<< MUST be done HERE!
}
Output('- before read: '+rdSt[reader.readyState]+"<br>");
reader.readAsText(file);
Output('- after read : '+rdSt[reader.readyState]+"<br>");
}
}
所以回调是强制性的 - 我只是没有合适的回调(onload
而不是 onloadend
)。
显然,newFile
始终未压缩,因为压缩甚至没有开始! ParseFile()
不能 return newFile
因为压缩仅以 onloadend()
结束(回调现在调用 UploadFile()
)。
作为最新练习,zlib.js "Gzip" 压缩不符合 HTTP GZIP 标准(或者我误用了另一个 JS 库)。
https://www.javascripture.com/ 帮我找到了相关的 Javascript 文档(稀缺资源)。
运气好的话,这种痛苦的辛苦工作会帮助别人...