[解決済み] ファイルの解凍
質問
表示したいのは OpenOffice ファイル、.odt と .odp をウェブブラウザを使用してクライアント側で表示したい。
これらのファイルは圧縮されたファイルです。Ajax を使用すると、サーバーからこれらのファイルを取得できますが、これらは圧縮されたファイルです。これらのファイルを解凍するには JavaScript を使って解凍する必要があるのですが、inflate.jsを使ってみました。 http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt を使ってみましたが、成功しませんでした。
どうすればいいのでしょうか?
どのように解決するのですか?
Javascriptで解凍ソフトを作りました。 動作します。
これは Andy G.P. Na のバイナリファイルリーダー と notmasteryet のいくつかの RFC1951 inflate ロジック。 . ZipFile クラスを追加しました。
の作業例です。
http://cheeso.members.winisp.net/Unzip-Example.htm
(デッドリンク)
ソースはこちら。
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip
(デッドリンク)
NB : リンクが切れています。すぐに新しいホストを探します。
ソースには ZipFile.htm のデモページと、zipfile クラス、inflate クラス、バイナリファイルリーダークラスの 3 つのスクリプトが含まれています。また、このデモは jQuery と jQuery UI に依存しています。 js-zip.zip ファイルをダウンロードすれば、必要なソースはすべてそこにあります。
アプリケーションのコードをJavascriptで書くとこんな感じです。
// In my demo, this gets attached to a click event.
// it instantiates a ZipFile, and provides a callback that is
// invoked when the zip is read. This can take a few seconds on a
// large zip file, so it's asynchronous.
var readFile = function(){
$("#status").html("<br/>");
var url= $("#urlToLoad").val();
var doneReading = function(zip){
extractEntries(zip);
};
var zipFile = new ZipFile(url, doneReading);
};
// this function extracts the entries from an instantiated zip
function extractEntries(zip){
$('#report').accordion('destroy');
// clear
$("#report").html('');
var extractCb = function(id) {
// this callback is invoked with the entry name, and entry text
// in my demo, the text is just injected into an accordion panel.
return (function(entryName, entryText){
var content = entryText.replace(new RegExp( "\\n", "g" ), "<br/>");
$("#"+id).html(content);
$("#status").append("extract cb, entry(" + entryName + ") id(" + id + ")<br/>");
$('#report').accordion('destroy');
$('#report').accordion({collapsible:true, active:false});
});
}
// for each entry in the zip, extract it.
for (var i=0; i<zip.entries.length; i++) {
var entry = zip.entries[i];
var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>";
// contrive an id for the entry, make it unique
var randomId = "id-"+ Math.floor((Math.random() * 1000000000));
entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId +
"'></span></span></div>\n";
// insert the info for one entry as the last child within the report div
$("#report").append(entryInfo);
// extract asynchronously
entry.extract(extractCb(randomId));
}
}
このデモは2つのステップで動作します。 このデモは
readFile
fn はクリックによって起動され、ZipFile オブジェクトをインスタンス化し、Zip ファイルを読み取ります。読み込みが完了すると、非同期のコールバックがあります (適度な大きさの Zip ファイルであれば、通常 1 秒以内に完了します) - このデモでは、コールバックは doneReading ローカル変数に保持されており、単純に
extractEntries
を呼び出すだけです。
を呼び出すだけで、提供された ZIP ファイルのすべてのコンテンツをやみくもに解凍します。 実際のアプリケーションでは、おそらく抽出するエントリの一部を選択することになるでしょう (ユーザーが選択できるようにするか、プログラムによって 1 つまたは複数のエントリを選択するなど)。
は
extractEntries
fnは全てのエントリを反復処理し、その後に
extract()
を呼び出し、コールバックを渡します。 エントリの解凍には時間がかかり、ZIP ファイル内の各エントリに対して 1 秒以上かかることがあります。これは、非同期が適切であることを意味します。extract コールバックは、抽出されたコンテンツをページ上の jQuery アコーディオンに追加するだけです。もしコンテンツがバイナリであれば、そのようにフォーマットされます(表示されません)。
動作はしますが、実用性はやや限定的だと思います。
EDIT
: JavascriptのZipFileは、IE9とChromeで、これよりもかなり速く解凍されます。コンパイルされたプログラムよりはまだ遅いですが、通常のブラウザの使用では十分な速さです。
もうひとつは、ストリーミングを行わないことです。基本的に、ZIP ファイルのコンテンツ全体をメモリに流し込んでいます。本当のプログラミング環境では、zip ファイルのメタデータのみを読み込み (たとえば、エントリごとに 64 バイト)、必要に応じて他のデータを読み込んで解凍することができます。 私の知る限り、javascript でそのような IO を行う方法はありません。したがって、唯一の選択肢は zip 全体をメモリに読み込んで、その中でランダムアクセスを行うことです。 つまり、大きなzipファイルの場合、システムメモリに無理な要求をすることになります。小さい zip ファイルではそれほど問題ではありません。
また ZIP 暗号化、WinZip 暗号化、ZIP64 など、unzipper にわざわざ実装しなかった多くの zip オプションがあります。
UTF-8 でエンコードされたファイル名。
といった具合です。(
EDIT
- は UTF-8 でエンコードされたファイル名を処理するようになりました)。ZipFileクラスは基本的なことを扱いますが。これらのうちのいくつかは、実装するのが難しくないでしょう。 私は
AES 暗号化クラス
を持っています。これは、暗号化をサポートするために統合することができます。Zip64をサポートすることは、おそらくJavascriptのほとんどのユーザにとって無意味でしょう。なぜなら、それは>4gbのzipファイルをサポートするためのものであり、ブラウザでそれらを展開する必要はありません。
また、バイナリコンテンツを解凍する場合のテストはしていません。今はテキストを解凍しています。 もし zip されたバイナリファイルがあれば、それを適切に処理するために ZipFile クラスを編集する必要があります。私はそれをきれいに行う方法を見つけ出していません。
バイナリファイルも扱えるようになりました。
EDIT - JSのunzipライブラリとデモを更新しました。 テキストに加え、バイナリファイルを扱えるようになりました。テキストファイルを読むときに使用するエンコーディングを指定できるようになりました。 また、デモも拡張され、ブラウザで XLSX ファイルを解凍する様子などを見ることができます。
というわけで、実用性や興味は限定的だと思いますが、動作はします。Node.jsでも動くんだろうなぁ。
関連
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] jQuery Ajax ファイルアップロード
-
[解決済み] Pythonでファイルを解凍する
-
[解決済み] JavaScriptの配列情報をcsvにエクスポートする方法(クライアント側)?
-
[解決済み] クライアントにJavaScriptファイルを強制的に更新させるには?
-
[解決済み] Node.js上のクライアント。Uncaught ReferenceError: require は定義されていません。
-
[解決済み】.netでプログラム的にファイルを解凍する。
-
[解決済み] AngularJSのエラーです。Cross Origin リクエストはプロトコルスキーム http, data, chrome-extension, https に対してのみサポートされています。
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] javascriptで文字列から関数を作成する方法はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] モバイルWeb HTML5フレームワークの選び方【終了しました
-
[解決済み] Chart.jsを使ってドーナツチャートの中にテキストを追加するには?
-
[解決済み] JavaScriptを使用してHTML要素に属性を追加/更新するには?
-
[解決済み] JavaScriptのtoString()関数をオーバーライドして、デバッグ用に意味のある出力を提供することは可能でしょうか?
-
[解決済み] JavaScriptでの大文字小文字を区別しない正規表現
-
[解決済み] Javascriptで動的に命名されたメソッドを呼び出すにはどうすればよいですか?
-
[解決済み] jQueryで入力ファイルが空かどうかをチェックする方法
-
[解決済み] JavaScriptでjson-objectのキーを取得する [重複].
-
[解決済み] JavaScript で css プロパティを使用して HTML 要素の背景色を設定する方法
-
[解決済み] 変異を伴わないオブジェクトからの値の削除