简体   繁体   English

在客户端上载之前进行文件压缩

[英]File compression before upload on the client-side

Basically I'll be working with large XML files (approx. 20 - 50 MB). 基本上我将使用大型XML文件(大约20 - 50 MB)。 These files needs to be uploaded on a server. 这些文件需要上传到服务器上。

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: 场景是这样的:

  1. Trying to upload 50 MB XML file 尝试上传50 MB的XML文件
  2. Before upload a grab it with Javascript and send it to the compressor. 在上传之前,使用Javascript抓取它并将其发送到压缩器。
  3. Upload the compressed file instead of the original one. 上传压缩文件而不是原始文件。

You can make use of JSZip . 你可以使用JSZip For input, it supports String/ArrayBuffer/Uint8Array/Buffer , but not blob s, which is what you get from an <input type="file"/> with javascript: 对于输入,它支持String / ArrayBuffer / Uint8Array / Buffer ,但不支持 blob ,这是使用javascript从<input type="file"/>获得的:

A File object is specific kind of a Blob, and can be used in any context that a Blob can File对象是特定种类的Blob,可以在Blob可以使用的任何上下文中使用

(link) (链接)

So you'll have to convert the blob/file to eg an ArrayBuffer first, eg using FileReader.readAsArrayBuffer() . 因此,您必须首先将blob /文件转换为例如ArrayBuffer,例如使用FileReader.readAsArrayBuffer() Note that this function works asynchronously, demanding callback usage. 请注意,此函数异步工作,要求回调使用。 There is also a FileReaderSync available, 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. 还有一个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 如果您的网站空间主机将php的指令max_file_uploads设置为较小的数字,这整个方法特别有用,现在您唯一需要担心的是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文件输入的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"]

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来放弃内容(bytearray))deflate算法是DEFLATE压缩数据格式规范版本1.3

There;s also a ByteArray::compress method which compresses using the zlib algorithm 还有一个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 2 For 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: 我的HTML代码嵌入swf:

<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];
    }
}

Consider reviewing this other stackoverflow post . 请考虑查看此其他stackoverflow帖子 Reading both answers paints a good picture of compression reality. 阅读这两个答案描绘了压缩现实的良好画面。

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. 我正在考虑实现压缩客户端的Silverlight of Flex解​​决方案,如果用户不想安装它,则压缩和解压缩文件服务器端。 Will update this post when a solution is found. 将在找到解决方案时更新此帖子。

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. 对于服务器,它将是带宽和压缩处理保护程序。

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? 另外,一个不太酷的选项,如果您的目标用户有点技术讽刺,为什么不让他们上传xml的.zip文件? Then on the server side you can unzip and process as needed. 然后在服务器端,您可以根据需要解压缩和处理。

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. 无论哪种方式在服务器端,你都需要解压缩/解压缩,如果你还没有想到解决方案,这应该很容易google解决方案。

With Silverlight, you can zip files on the client side, and this approach works in all major browsers. 使用Silverlight,您可以在客户端压缩文件,这种方法适用于所有主流浏览器。 Moreover, you can interact with your Silverlight widget via JavaScript. 此外,您可以通过JavaScript与Silverlight小部件进行交互。 Also, if a user needs to upload several files, your Silverlight widget can show a single dialog for selecting all the files. 另外,如果用户需要上传多个文件,您的Silverlight插件可以显示选择所有文件的单个对话框。 The only drawback is that your clients must install the Silverlight plugin. 唯一的缺点是您的客户必须安装Silverlight插件。

有一些免费提供的huffman压缩javascript库,例如https://github.com/wilkerlucio/huffman_js,但我认为你的任务是不可能的,因为使用javascript和html,不可能将大量数据加载到浏览器或客户端的内存中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM