Web Service

Excel/PowerPoint/Wordファイルから画像を取り出す Web サービスを作ってみた

Office 2007/2010/2013 の Excel/PowerPoint/Word ファイル(.xlsx・.pptx・.docx など)は、zip 形式で圧縮されていて、拡張子を .zip に変えると、使われている画像などのメディアファイルを簡単に取り出せます。

office

それと同じことをする、Web サービス を作ってみました。Web ブラウザーに Office ファイルをドロップすると、メディアファイルだけ残した zip ファイルを作成し、ダウンロードできます。

Excel/PowerPoint/Wordファイルから画像の取り出し

クライアント側の JavaScript で zip の展開をしているため、サーバーにはファイル情報を送っていません。

ファイルをコピーして拡張子を zip に変換して画像を取り出すのは、少しだけ手間ではありますが、はたして、このサイトを開いて画像を取り出すのとどっちが楽なのか……。

コード

JavaScript で、zip ファイルを扱える JSZip を使いました。

ファイルの中身を走査し、Office 文書のメディアフォルダー以外のものは、元の zip から削除することで、メディアファイルのみの zip を作っています(ファイルを取り出して再度 zip ファイルを作ると遅かったので)。

zip ファイルのダウンロード保存は、JSZip のサンプルでも使われている FileSaver.js を使っています。

officemedia.js
(function ($) {
    $("#target").on("drop", function (evt) {
        // ファイルをドロップした場合
        extractMedia(evt.originalEvent.dataTransfer.files);
        return false;
    }).on("dragenter", function () {
        return false;
    }).on("dragover", function () {
        return false;
    }).click(function () {
        // 画面をクリックした場合、ファイル選択のダイアログを開く
        $("#file").click();
        return false;
    });

    // ダイアログからファイルを選択した場合
    $("#file").on("change", function (evt) {
        extractMedia(evt.target.files);
    });

    // zip ファイル(Office 文書)から、メディアフォルダーのみ残す
    function extractMedia(files) {
        for (var i = 0, f; f = files[i]; i++) {
            var reader = new FileReader();
            reader.onload = (function (theFile) {
                return function (e) {

                    try {
                        var count = 0;
                        var zip = new JSZip(e.target.result);

                        // zip の内容を走査
                        $.each(zip.files, function (index, zipEntry) {
                            if (zipEntry.name.lastIndexOf('word/media/', 0) !== 0 &&
                                zipEntry.name.lastIndexOf('ppt/media/', 0) !== 0 &&
                                zipEntry.name.lastIndexOf('xl/media/', 0) !== 0) {
                                zip.remove(zipEntry.name);
                            } else {
                                count++;
                            }
                        });

                        if (count > 0) {
                            // メディアフォルダーがあった場合のみ、保存
                            var blob = zip.generate({ type: "blob" });
                            saveAs(blob, "media.zip");
                        } else {
                            alert("メディアファイルは見つかりませんでした。");
                        }
                    } catch (e) {
                        alert("Error reading " + theFile.name + " : " + e.message);
                    }
                }
            })(f);
            reader.readAsArrayBuffer(f);
        }
    }
})(jQuery);