0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

laravelでcsvファイルを中身の値ごとに分割した後、zipにまとめてダウンロードさせたい

Last updated at Posted at 2023-08-08

はじめに

csvファイルをカラムの値ごとに分けたい時ってありますよね。
csvを分割した後、zipにまとめて、ダウンロードまでさせる処理を書いてみました。

今回やること

  • id(id),name(名前),age(年齢),address(都道府県)の4つのカラムでできたcsvファイルをaddress(都道府県
    名)ごとに分けてそれぞれcsvファイルを生成したのち、zipファイルにまとめてダウンロードさせる
  • 画面、ルーティングなどは省略しますm(__)m
  • バリデーションもしてません

用意したcsvファイル

  • id,name,age,addressの4つのカラムでできたcsvファイル(25行くらい)
    ↓↓ こんな感じ
    Screen Shot 2023-08-08 at 9.56.48.png

laravel-zipstreamの準備

  • laravel-zipstreamのインストール
composer require stechstudio/laravel-zipstream

今回実装した処理(コントローラ)

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use STS\ZipStream\ZipStreamFacade as Zip;

class ZipController extends Controller
{
    public function __invoke(Request $request)
    {
        $csvFile = $request['csvfile'];

        if ($csvFile->getClientOriginalExtension() !== "csv") {
            throw new \Exception('csvファイルを入れてくれ');
        }

        if ($csvFile->isValid()) {
            $csvData = file_get_contents($csvFile->getPathname());

            $rows = explode("\n", $csvData);

            // カラムを取得する
            $header = str_getcsv(array_shift($rows));

            $columnToFetch = 'address';

            $filePaths = [];

            foreach ($rows as $row) {
                $data = str_getcsv($row);

                $filePath = 'public/csv/' . $data[array_search($columnToFetch, $header)] . '.csv';

                if (!Storage::exists($filePath)) {
                    $newHeader = implode(",", $header);
                    Storage::put($filePath, $newHeader);
                }

                Storage::append($filePath, $row);
                $filePaths[] = storage_path('app/' . $filePath);
            }

            $uniqueFilePaths = array_unique($filePaths);

            $zipFile = 'download.zip';
            $destinationDirectory = storage_path('app/public/zip');
            // ここでzipファイル生成して指定した場所に保存してます
            Zip::create($zipFile, $uniqueFilePaths)->saveTo($destinationDirectory);

            return Storage::download('public/zip/download.zip', 'download.zip', []);
        }

        return 'エラーがおきた';
    }
}

これでダウンロードされたら成功づえす。

注意したいところ
ファイル名が日本語の時envに設定しないと狙った挙動にならないことがあったので、ファイル名が日本語の時は下記の値をenvに設定しましょう

ZIPSTREAM_FILE_SANITIZE=false

おわりに

  • 他にもっといい方法があれば教えてください!
  • laravel-zipstream は結構簡単に使えて便利なのでzip生成したい時はおすすめです。
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?