2011-12-04 73 views
9

基本上,我將使用大型XML文件(大約20-50 MB)。這些文件需要上傳到服務器上。在客戶端上傳之前進行文件壓縮

我知道用JavaScript觸摸文件是不可能的,也不可能在客戶端實現HTTP壓縮。

我的問題是,如果任何解決方案(閃存/動作腳本)壓縮文件,並有一個javascript API?

的情況是這樣的:

  1. 要上傳50 MB的XML文件
  2. 上傳之前抓住它的JavaScript,並將其發送到壓縮機。
  3. 上傳壓縮文件,而不是原始文件。
+0

我發現了這個,但我從來沒有使用它(並沒有Flash在這裏):http://jszip.stuartk.co.uk/ – AsTheWormTurns

+0

感謝您的鏈接,但基本上我需要一個解決方案,適用於所有主要瀏覽器如IE7 +,FF,Safari和Chrome。 – feketegy

回答

5

Flash的內置實現的ByteArray的具有方法(ByteArray::deflate放氣的ByteArray的內容()DEFLATE算法是DEFLATE Compressed Data Format Specification version 1.3

有;同時是個ByteArray::compress方法,其壓縮使用zlib算法

挺住了一下,我給你一些示例代碼使用這個類,並將其呈現給JavaScript。

編輯

我上傳的http://www.filefactory.com/file/cf8a39c/n/demo5.zip

EDIT 2文件對於那些誰也無法下載文件:

我ActionScript代碼在demo5.fla(編譯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); 
    } 
} 

我的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> 

最後的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]; 
    } 
} 
+0

謝謝,我正在等待它。 :)另外,使用Flash的文件處理很容易嗎?我猜爲了得到你需要使用Flash的文件對話框的文件,然後壓縮它,然後以某種方式將它發送到服務器... – feketegy

+0

@feketegy,我已經在32分鐘前添加了上傳(不知道爲什麼之後我添加的評論沒有發佈)。無論如何,它中的html包含很明顯的javascript(帶有註釋),所以如果你什麼都沒有得到,不要問它。一個問題是:你將不得不通過http://域來運行html,或者向你的flash播放器添加一個例外(你的選擇) –

+0

感謝你們,我還可以通過,閃光燈?在JavaScript中,我只能訪問文件的路徑,而沒有其他。所以一旦文件被壓縮,你有什麼建議如何將它發送到服務器? – feketegy

0

有一些JavaScript霍夫曼壓縮自由使用,例如https://github.com/wilkerlucio/huffman_js的庫,但我認爲,你的任務是不可能的,因爲用JavaScript和HTML這是不可能的巨大的數據加載到瀏覽器或客戶端的內存。

+0

嘿,謝謝,但正如我在前面的評論中提到的,我需要一個適用於IE7 +和其他主流瀏覽器的解決方案。這個解決方案有些是實驗性的Javascript,我不相信可以處理大型XML文件,大小爲40-50 MB。 – feketegy

+0

@feketegy:這只是一個建議。你可以自己做。 – Bytemain

+0

查看此鏈接http://gildas-lormeau.github.io/zip.js/ –

1

如果因爲某種原因你無法獲得適用於所有主流瀏覽器的JavaScript解決方案,我知道這裏有一個AS3壓縮庫:http://code.google.com/p/ascompress/

此外,如果您的目標用戶有點技術含量較高,那麼爲什麼不讓他們上傳xml的.zip文件?然後在服務器端,您可以根據需要解壓縮並進行處理。

無論哪種方式在服務器端,你會想要解壓縮/解壓縮,如果你還沒有一個解決方案,這應該很容易谷歌的解決方案。 。

+0

感謝您的鏈接。這個解決方案是否有Javascript API?我不熟悉Flash/Actionscript(我只是一個用戶)。另外,我不能讓用戶事先壓縮XML文件。不幸的是,這必須是一個自動化的過程,雖然這將是理想的... – feketegy

+0

你可以在ActionScript中處理它,因爲它有它自己的文件瀏覽器。如果您需要它與JavaScript進行交談,但是您可以使用AS3的ExternalInterface。 Pranav的上面有一個很好的解決方案。 – ToddBFisher

1

使用Silverlight,你可以在客戶端壓縮文件,這種方法適用於所有主流瀏覽器。而且,您可以通過JavaScript與Silverlight小部件進行交互。此外,如果用戶需要上傳多個文件,則Silverlight小部件可以顯示一個單個對話框,用於選擇所有文件。唯一的缺點是你的客戶必須安裝Silverlight插件。

1

請考慮查看此其他stackoverflow post。閱讀這兩個答案描繪了壓縮現實的一張好照片。

我正在考慮實施壓縮客戶端的Silverlight of Flex解​​決方案,如果用戶不想安裝它,請壓縮和解壓縮文件服務器端。將在找到解決方案時更新此帖子。

安裝控制器將作爲節省時間的銷售給用戶,這通常是正確的。對於服務器來說,這將是一個帶寬和壓縮處理保護程序。

4

您可以使用JSZip。對於輸入,它支持String/ArrayBuffer/Uint8Array/Buffer,但blob s,這是你從一個<input type="file"/>得到什麼使用javascript:

File對象是特定種類的Blob的,並且可以在任何上下文中使用一個斑點可以

(link)

所以你必須將BLOB /文件轉換成如首先是ArrayBuffer,例如使用FileReader.readAsArrayBuffer()。請注意,此功能異步工作,要求回調使用。還有一個可用的FileReaderSync,但「此接口僅在工作中可用,因爲它啓用了可能會阻塞的同步I/O」,所以我沒有看到使用它的好處。

編輯,我不知道,但我相信你現在可以跳過blob-> ArrayBuffer轉換和壓縮簡單File對象。

這整個的做法是,如果PHP的指令max_file_uploads是特別有用的通過你的網站主機設置爲一個小數目,對於現在的唯一的事情你必須要擔心的是upload_max_filesize

作爲參考,代碼示例摘錄的內容(使用JQuery),用於把一個multiple文件輸入的幾個文件提交前的郵編:

// 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 

服務器端方面,您將訪問$_FILES["fileZip"]

+0

您可以跳過版本3+中的blob-> ArrayBuffer轉換。但對於較舊的版本(在我的情況下爲2.6),您的解決方案非常有用 –

相關問題