0
0

CSVファイルアップロードが上手くいかない時の解決策

Last updated at Posted at 2024-02-02

起こったこと

PHP(laravel)でCSVアップロード機能を作成していたところ起こった事象。
CSVファイルのn行目のヘッダーの内容を確認しデータをDBに保存するという機能を作成していたのだが、ヘッダーの1列目を認識してくれないエラーが発生。
しかし、該当のCSVファイルはExcelから「名前を付けて保存」すると発生せず、正常にアップロードされるため困り果てていた。
CSVファイルの権限によるものではないかと考え調査していたが、めぼしい調査結果は得られずにいた。

原因

WinMergeで、元のファイルと「名前を付けて保存」し直したファイルを比較したところ、原因が発覚。
原因は「空行」だった。
実はCSVファイルデータのn-1行目には空行が入っており、それがSplFileObject::SKIP_EMPTYによって読み飛ばされていたことで、n行目のデータではなくn+1行目をヘッダーとして認識してしまい、それによりヘッダーが認識されずエラーが発生していたのだ。

修正前データ
$file->setFlags(
          \SplFileObject::READ_CSV |      // CSVとして行を読み込み
          \SplFileObject::READ_AHEAD |    // 先読み/巻き戻しで読み込み
          \SplFileObject::SKIP_EMPTY |    // 空行を読み飛ばす
          \SplFileObject::DROP_NEW_LINE   // 行末の改行を読み飛ばす
        );        

$header = $file->fgetcsv();
for ($i = 1; $i < (n-1); $i++) {
                $header = $file->fgetcsv();
            }

ちなみに「名前を付けて保存」し直したファイルでは、空行部分に「,(カンマ)」が自動で入れられていたため、空行扱いされず正常にアップロードが完了してしまっていた。

解決策

ヘッダーの読み込みを1回減らしてあげることで解決した。

修正後データ
$file->setFlags(
          \SplFileObject::READ_CSV |      // CSVとして行を読み込み
          \SplFileObject::READ_AHEAD |    // 先読み/巻き戻しで読み込み
          \SplFileObject::SKIP_EMPTY |    // 空行を読み飛ばす
          \SplFileObject::DROP_NEW_LINE   // 行末の改行を読み飛ばす
        );        

$header = $file->fgetcsv();
for ($i = 0; $i < (n-2); $i++) {
                $header = $file->fgetcsv();
            }

終わりに

SplFileObjectの存在を完全に見落としており、解決に2週間費やしました…。
大体のエラーはファイルのせいじゃなく自分が書いたコードのせいだという自分への戒めです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0