Javascript 客户端上传前文件压缩
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8377268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
File compression before upload on the client-side
提问by feketegy
Basically I'll be working with large XML files (approx. 20 - 50 MB). These files needs to be uploaded on a server.
基本上,我将使用大型 XML 文件(大约 20 - 50 MB)。这些文件需要上传到服务器上。
I know it isn't possible to touch the files with javascript, nor to implement HTTP compression on the client-side.
我知道不可能用 javascript 接触文件,也不可能在客户端实现 HTTP 压缩。
My question is that if any solution exists (flash / action script) that compresses a file and has a javascript API?
我的问题是,是否存在压缩文件并具有 javascript API 的任何解决方案(闪存/动作脚本)?
The scenario is this:
场景是这样的:
- Trying to upload 50 MB XML file
- Before upload a grab it with Javascript and send it to the compressor.
- Upload the compressed file instead of the original one.
- 尝试上传 50 MB XML 文件
- 在上传之前用 Javascript 抓取它并将其发送到压缩器。
- 上传压缩文件而不是原始文件。
采纳答案by Pranav Hosangadi
Flash's inbuilt implementation of ByteArray has a method (ByteArray::deflate
to deflate the contents (of the bytearray) The deflate algorithm is the DEFLATE Compressed Data Format Specification version 1.3.
Flash 内置的 ByteArray 实现有一个方法(ByteArray::deflate
对(字节数组的)内容进行压缩)该压缩算法是DEFLATE 压缩数据格式规范 1.3 版。
There;s also a ByteArray::compress
method which compresses using the zlibalgorithm
还有一种ByteArray::compress
使用zlib算法进行压缩的方法
Hold on a bit, I'll write you some sample code to use this class and expose it to JavaScript.
稍等一下,我会为您编写一些示例代码来使用这个类并将其公开给 JavaScript。
EDIT
编辑
I've uploaded the file at http://www.filefactory.com/file/cf8a39c/n/demo5.zip
我已将文件上传至http://www.filefactory.com/file/cf8a39c/n/demo5.zip
EDIT 2For those who couldn't download the files:
编辑 2对于那些无法下载文件的人:
My ActionScript code in demo5.fla (compiled to demo5.swf)
我在 demo5.fla 中的 ActionScript 代码(编译为 demo5.swf)
import flash.external.ExternalInterface;
import flash.net.FileReference;
import flash.events.Event;
import flash.utils.ByteArray;
if(ExternalInterface.available) {
//flash.system.Security.allowDomain("localhost");
ExternalInterface.addCallback("deflate", doDeflate);
ExternalInterface.addCallback("compress", doCompress);
}
var method:String="deflate";
var b:ByteArray;
function doCompress(_data:String):void {
method="compress";
exec(_data);
}
function doDeflate(_data:String):void {
method="deflate";
exec(_data);
}
function exec(_data:String):void {
b=new ByteArray();
b.writeUTFBytes(_data);
b.position=0;
if(method=="compress") {
b.compress();
} else if(method=="deflate") {
b.deflate();
}
executed();
}
function executed():void {
if(ExternalInterface.available) {
b.position=0;
var str:String=b.readUTFBytes(b.bytesAvailable);
ExternalInterface.call("onExec", str);
}
}
My HTML code to embed the swf:
我要嵌入 swf 的 HTML 代码:
<button onclick="doDeflate()">Deflate</button>
<button onclick="doCompress()">Compress</button>
<div id="flashContent">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="1" height="1" id="demo5" align="middle">
<param name="movie" value="demo5.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="play" value="true" />
<param name="loop" value="true" />
<param name="wmode" value="window" />
<param name="scale" value="showall" />
<param name="menu" value="true" />
<param name="devicefont" value="false" />
<param name="salign" value="" />
<param name="allowScriptAccess" value="always" />
<embed src="demo5.swf" quality="high" bgcolor="#869ca7"
width="1" height="1" name="demo5" align="middle"
play="true" loop="false" quality="high" allowScriptAccess="always"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">
</embed>
</object>
</div>
and finally the javascript code:
最后是javascript代码:
function doDeflate() {
var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu";
//DATA CONTAINS DATA TO BE DEFLATED
thisMovie("demo5").deflate(data);
}
function doCompress() {
var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu";
//DATA CONTAINS DATA TO BE DEFLATED
thisMovie("demo5").compress(data);
}
function onExec(data) {
//DATA CONTAINS THE DEFLATED DATA
alert(data);
}
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
回答by phil294
You can make use of JSZip. For input, it supports String/ArrayBuffer/Uint8Array/Buffer, but notblob
s, which is what you get from an <input type="file"/>
with javascript:
您可以使用JSZip。对于输入,它支持String/ArrayBuffer/Uint8Array/Buffer,但不支持blob
s,这是您从<input type="file"/>
javascript 中得到的:
A File object is specific kind of a Blob, and can be used in any context that a Blob can
File 对象是 Blob 的特定类型,可以在 Blob 可以使用的任何上下文中使用
So you'll have to convert the blob/file to e.g. an ArrayBuffer first, e.g. using FileReader.readAsArrayBuffer()
. Note that this function works asynchronously, demanding callback usage. There is also a FileReaderSyncavailable, yet "This interface is only available in workers as it enables synchronous I/O that could potentially block", so I don't see any good in using it.
因此,您必须首先将 blob/文件转换为例如 ArrayBuffer,例如使用FileReader.readAsArrayBuffer()
. 请注意,此函数是异步工作的,需要使用回调函数。还有一个FileReaderSync可用,但“此接口仅在工作人员中可用,因为它启用可能会阻塞的同步 I/O”,所以我认为使用它没有任何好处。
(EDIT. I'm not sure but I believe you can skip the blob->ArrayBuffer conversion now and simply zip the File object.)
(编辑。我不确定,但我相信您现在可以跳过 blob->ArrayBuffer 转换,只需压缩 File 对象。)
This whole approach is specially useful if php's directive max_file_uploads
was set to a small number by your webspace host, for now the only thing you'll have to worry about is upload_max_filesize
如果max_file_uploads
您的 webspace 主机将php 的指令设置为一个小数字,则整个方法特别有用,现在您唯一需要担心的是upload_max_filesize
For reference, a code sample excerpt follows (using JQuery
) for putting several files of one multiple
file input in a zip before submitting:
作为参考,代码示例摘录如下(使用JQuery
),用于multiple
在提交之前将一个文件输入的多个文件放入一个 zip 文件中:
// onclick:
var fileInput = $(':file');
var files = [];
$.each(fileInput[0].files, function(i, file) {
files.push(file);
});
var zip = new JSZip();
function addFileToZip(n) {
if(n >= files.length) {
zippingComplete(zip.generate({type:"blob", compression:"deflate"}));
return;
}
var file = files[n];
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function() {
arrayBuffer = this.result;
zip.file(file.name, arrayBuffer);
addFileToZip(n + 1);
};
fileReader.readAsArrayBuffer(file);
}
addFileToZip(0);
function zippingComplete(zip) {
formData = new FormData();
formData.append('fileZip', zip);
formData.append("param1", "blah");
$.ajax({
data: formData,
//... etc
Server-side-wise, you'll access $_FILES["fileZip"]
.
在服务器端,您将访问$_FILES["fileZip"]
.
回答by Stan Jordan
With Silverlight, you can zip files on the client side, and this approach works in all major browsers. Moreover, you can interact with your Silverlight widget via JavaScript. Also, if a user needs to upload several files, your Silverlight widget can show a singledialog for selecting all the files. The only drawback is that your clients must install the Silverlight plugin.
使用 Silverlight,您可以在客户端压缩文件,这种方法适用于所有主要浏览器。此外,您可以通过 JavaScript 与 Silverlight 小部件交互。此外,如果用户需要上传多个文件,您的Silverlight控件可以显示一个单一的选择所有文件对话框。唯一的缺点是您的客户端必须安装 Silverlight 插件。
回答by Ben Gripka
Consider reviewing this other stackoverflow post. Reading both answers paints a good picture of compression reality.
考虑查看其他stackoverflow 帖子。阅读这两个答案可以很好地了解压缩现实。
I'm considering implementing a Silverlight of Flex solution that compresses client side and if the user doesn't want to install it, compress and decompress the file server side. Will update this post when a solution is found.
我正在考虑实施 Flex 解决方案的 Silverlight,该解决方案压缩客户端,如果用户不想安装它,则压缩和解压缩文件服务器端。找到解决方案后将更新此帖子。
Installing the control would be sold to the user as a time saver, which is normally true. For the server, it would be a bandwidth and compression processing saver.
安装控件将作为节省时间的方式出售给用户,这通常是正确的。对于服务器,它将是带宽和压缩处理保护程序。
回答by ToddBFisher
If for whatever reason you can't get a solution to work in JavaScript for all major browsers, I know of an AS3 compression library here: http://code.google.com/p/ascompress/.
如果由于某种原因您无法获得适用于所有主要浏览器的 JavaScript 的解决方案,我知道这里有一个 AS3 压缩库:http: //code.google.com/p/ascompress/。
Also, a less cooler option, if your target users are somewhat tech savy why not have them upload a .zip file of the xml? Then on the server side you can unzip and process as needed.
此外,还有一个不太酷的选择,如果您的目标用户有点精通技术,为什么不让他们上传 xml 的 .zip 文件?然后在服务器端,您可以根据需要解压缩和处理。
Either way on the server side you'll want to unzip/decompress, which should be easy to google for solutions if you don't already have one in mind.
无论哪种方式在服务器端,您都需要解压缩/解压缩,如果您还没有想到解决方案,应该很容易在谷歌上搜索解决方案。
回答by Gigamegs
There some javascript library of huffman compression freely available, for example https://github.com/wilkerlucio/huffman_jsbut I think that your task is impossible because with javascript and html it's not possible to load huge data into the browser or client's memory.
有一些免费提供的霍夫曼压缩的 javascript 库,例如https://github.com/wilkerlucio/huffman_js但我认为您的任务是不可能的,因为使用 javascript 和 html 不可能将大量数据加载到浏览器或客户端的内存中。