「注文の多いXOOPS屋」で公開中のダウンロードが破損。原因はFTPクライアント

先日、注文の多いXOOPS屋のダウンロードコーナーで公開しているファイルが破損していて、ZIPファイルが解凍できないというご報告をいただき、ファイルを修正しました。

ファイル破損のきっかけはサイト移転

ご報告いただいてから、いったい何が原因なのか調べるために自分でもダウンロードしてみたのですが、やっぱりZIPファイルが解凍できない。

それも一つ二つのファイルでなく、ほぼ全てのzipファイルがダメでした。

それで元ファイルをFTPを使ってサーバからダウンロードして、かなり前のバックアップファイル(こちらは解凍できた)と比較してみました。

そうしてみると、解凍できた以前のバックアップファイルと解凍できなかったファイルの違いは改行コードだけでした。

OKだったバックアップファイルの改行コードはLF

NGだったファイルの改行コードはCR+LF

これで原因に思い当たりました。

たいていのFTPクライアントにはアスキーモードとかテキストモードと呼ばれる転送モードがあります。

これはWindows OSとLinux系OSとで使われてる改行コードが異なるので転送時に自動的に変換するためのモードです。

Windows→Linuxにアップロード時は改行コードCR+LFをLFに。
Linux→Windowsにダウンロードするときは、LFをCR+LFに変換します。

そう。これが問題。
通常はファイルの拡張子をみて自動でテキストモードとバイナリモード(改行コードを変換しない)を切り替えてくます。

それが今のサーバにサイト移転するためにダウンロードしたときは、ZIPファイルをテキストモードでダウンロードしてしまったのだろうと思います。

それでファイル内のLFがCR+LFに変換されてしまい、結果ファイルが破損したのだと思われます。

ちゃんとXXX.zipってファイル名だったらこんなことは起きなかったと思います。

今回、こんなことが発生したのはXOOPS Cubeのd3downloadsモジュールのファイル保持方法も原因のひとつなってます。

d3downloadsはアップロードしたファイルをサーバ上で拡張子なしのファイル名で保存するようになってます。

恐らくこの拡張子無しのファイルをFTPクライアントがテキストファイルであると判断したんでしょうね。

CR+LFをLFにしよう

さて原因がだいたいわかったところで、解決方法としては壊れたファイルのCR+LFをLFにすることになります。

で、TwitterやfacebookでCR+LFをLFにするうまい方法がないか聞いてみたら、2つの方法を教えていただきました。

  1.  phpで変換してしまう
  2.  FTPクライアントでテキストモードで転送する

phpで変換

教えてもらったのは次のような方法

$ cat current_foo | php -r 'echo str_replace("\r\n", "\n", file_get_contents("php://stdin"));' > new_foo

これをベースに複数ファイルまとめて複数ファイルを変換したかったので、下記にして実行

find . -type f | xargs -I{} sh -c "cat {}| php -r 'echo str_replace(\"\r\n\", \"\n\", file_get_contents(\"php://stdin\"));' >../ok/{}"

解凍ソフトでは解凍できませんでしたが、Macのunzipコマンドではエラー吐きながらも一応解凍できました。

FTPクライアントでテキストモードで転送する

元々の原因がFTPクライアントのテキストモードでの改行コード変換なのだから、同じ事をやってしまえばいいだろうということですね。

こちらも試してみたところ解凍ソフトでは解凍できませんでしたが、Macのunzipコマンドではエラー吐きながらも一応解凍できました。

解凍できても破損してる

なんとかCR+LFをLFに変換することでムリヤリながらも解凍できるようにはなったんですが、残念ながら解凍されたファイルをみていくと、けっこうファイル壊れてました…orz

ZIPファイルに圧縮されていた画像ファイルはほぼ復元NG…
テキストファイルは中身がいくらか破損…(ちゃんと全部復旧できたファイルもあり)

ちょっとそのままでは使えない結果となってしまいました。

バックアップ大事

で、最終的にどうしたかというと、大半のファイルは破損してない古いバックアップから復旧させました^^;

2ファイルだけバックアップに残ってたのが古いバージョンだったので、更新履歴となんとかムリヤリ解凍できた範囲のファイルからの情報をもとに、古いバックアップに修正を適用して復旧させました。

改行コードの変換したら復旧できる思ったのにちょっとアテがはずれちゃいました。

ってことで皆さん、バックアップ大事!
特に、何か変更を加える前のバックアップは重要!!
今回も移転前のデータが残ってたのが幸いしました。

[PR]

投稿者プロフィール

龍司
XOOPS CubeとNetCommons3のカスタマイズをよくやってます。
技術ネタは https://qiita.com/RyujiAMANO に書くコトがおおいです。