Laravel-excel: [์งˆ๋ฌธ] ๋Œ€๊ธฐ ์ค‘์ธ ์ฒญํฌ ์ฝ๊ธฐ ์ž‘์—… ์‹คํŒจ

์— ๋งŒ๋“  2018๋…„ 10์›” 17์ผ  ยท  21์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Maatwebsite/Laravel-Excel

์ฝ์–ด์ฃผ์„ธ์š”: ํ…œํ”Œ๋ฆฟ์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! ์ •๋ณด๊ฐ€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๋ฌธ์ œ๋Š” ์„ ํƒ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Laravel-Excel์˜ ๊ธฐ์—ฌ ์ง€์นจ(https://laravel-excel.maatwebsite.nl/docs/3.1/getting-started/contributing) ๋ฐ ํ–‰๋™ ๊ฐ•๋ น(https://github.com/Maatwebsite/Laravel-Excel/ blob/3.1/CODE_OF_CONDUCT.md)? ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ•จ์œผ๋กœ์จ ๋ชจ๋“  ์‚ฌ๋žŒ์„ ์กด์ค‘ํ•˜๋Š” ๋งˆ์Œ์œผ๋กœ ๋Œ€ํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ์ค€์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [BUG] [PROPOSAL] [QUESTION] ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฌธ์ œ์— ์ ‘๋‘์–ด๋กœ ๋ถ™์ด์‹ญ์‹œ์˜ค.

์ „์ œ ์กฐ๊ฑด

๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•œ ๊ฒฝ์šฐ ๋Œ€๊ด„ํ˜ธ ์‚ฌ์ด์— X๋ฅผ ๋„ฃ์œผ์‹ญ์‹œ์˜ค.
  • [ ] ์ฝ”๋“œ ์™ธ๋ถ€์—์„œ ๋™์ž‘์„ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋Š” Laravel Excel๋กœ ๊ฒฉ๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • [x] ๋ฌธ์ œ๊ฐ€ ์•„์ง ์ œ์ถœ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.
  • [x] ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” PR์ด ์ œ์ถœ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฒ„์ „

๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ์ฆ๋ช…ํ•  ๋•Œ๋Š” ์ตœ๋Œ€ํ•œ ์ •ํ™•ํ•˜๊ณ  ์™„์ „ํ•˜๊ฒŒ ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค.
  • PHP ๋ฒ„์ „: 7.1.23
  • ๋ผ๋ผ๋ฒจ ๋ฒ„์ „: 5.6
  • ํŒจํ‚ค์ง€ ๋ฒ„์ „: 3.1.2

์„ค๋ช…

ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•˜๊ณ (.xlsx, .ods ๋˜๋Š” .csv์ธ์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Œ) ์ฒญํฌ ์ฝ๊ธฐ๋ฅผ ๋Œ€๊ธฐ์—ด์— ์ถ”๊ฐ€ํ•˜๋ฉด ๋‚ด failed_jobs ํ…Œ์ด๋ธ”์—์„œ ๋‹ค์Œ ์˜ค๋ฅ˜์™€ ํ•จ๊ป˜ ์ž‘์—…์ด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
InvalidArgumentException: File "/tmp/SWQF2KfyI6BP0k1x" does not exist. in /home/miguel/www/html/proliste/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:137

๋ฒˆ์‹ ๋‹จ๊ณ„

์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฌธ์ œ๋ฅผ ์‰ฝ๊ฒŒ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก Excel ํŒŒ์ผ ๋˜๋Š” ๋ณต์ œ ์ €์žฅ์†Œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘:

๋‚˜๋Š” ์ผ์ด ์‹คํŒจํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ค. ์ž‘์—…์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ ์—†์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ํ–‰๋™:
failed_jobs ํ…Œ์ด๋ธ”์˜ ์Šคํƒ ์ถ”์ :

InvalidArgumentException: File "/tmp/SWQF2KfyI6BP0k1x" does not exist. in /home/miguel/www/html/proliste/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:137
Stack trace:
#0 /home/miguel/www/html/proliste/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php(389): PhpOffice\PhpSpreadsheet\Shared\File::assertFile('/tmp/SWQF2KfyI6...')
#1 /home/miguel/www/html/proliste/vendor/maatwebsite/excel/src/Jobs/ReadChunk.php(82): PhpOffice\PhpSpreadsheet\Reader\Xlsx->load('/tmp/SWQF2KfyI6...')
#2 [internal function]: Maatwebsite\Excel\Jobs\ReadChunk->handle()
#3 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array)
#4 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#5 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#6 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/Container.php(564): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#7 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(94): Illuminate\Container\Container->call(Array)
#8 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object(Maatwebsite\Excel\Jobs\ReadChunk))
#9 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Maatwebsite\Excel\Jobs\ReadChunk))
#10 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#11 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(49): Illuminate\Bus\Dispatcher->dispatchNow(Object(Maatwebsite\Excel\Jobs\ReadChunk), false)
#12 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(83): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\DatabaseJob), Array)
#13 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(326): Illuminate\Queue\Jobs\Job->fire()
#14 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(276): Illuminate\Queue\Worker->process('database', Object(Illuminate\Queue\Jobs\DatabaseJob), Object(Illuminate\Queue\WorkerOptions))
#15 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(118): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\DatabaseJob), 'database', Object(Illuminate\Queue\WorkerOptions))
#16 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(101): Illuminate\Queue\Worker->daemon('database', 'default', Object(Illuminate\Queue\WorkerOptions))
#17 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(85): Illuminate\Queue\Console\WorkCommand->runWorker('database', 'default')
#18 [internal function]: Illuminate\Queue\Console\WorkCommand->handle()
#19 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array)
#20 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#21 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#22 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Container/Container.php(564): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#23 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Console/Command.php(179): Illuminate\Container\Container->call(Array)
#24 /home/miguel/www/html/proliste/vendor/symfony/console/Command/Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#25 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Console/Command.php(166): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#26 /home/miguel/www/html/proliste/vendor/symfony/console/Application.php(886): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#27 /home/miguel/www/html/proliste/vendor/symfony/console/Application.php(262): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#28 /home/miguel/www/html/proliste/vendor/symfony/console/Application.php(145): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#29 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Console/Application.php(89): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#30 /home/miguel/www/html/proliste/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(122): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#31 /home/miguel/www/html/proliste/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#32 {main}

์ถ”๊ฐ€ ์ •๋ณด

์Šคํƒ ์ถ”์ ์—์„œ ์˜ค๋ฅ˜๊ฐ€ PhpSpreadsheet ์—์„œ ์˜จ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฝ๊ธฐ/์“ฐ๊ธฐ ๊ถŒํ•œ ๋ฌธ์ œ์ธ ์ค„ ์•Œ์•˜๋Š”๋ฐ /tmp ํด๋”๊ฐ€ 777์ด๊ณ  php.ini ํŒŒ์ผ์ด ์„ค์น˜ ์ดํ›„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค(์˜ˆ์™ธ upload_max_filesize post_max_size).

๋‚ด ์—ฐ๋ฝ์ฒ˜๊ฐ€์ ธ์˜ค๊ธฐ ํด๋ž˜์Šค:

<?php

namespace App\Imports;

use App\Contact;
use App\Rubric;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\Importable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class ContactsImport implements ToModel, WithBatchInserts, WithChunkReading, WithHeadingRow, ShouldQueue
{
    use Importable;

    /**
    * <strong i="10">@param</strong> array $row
    *
    * <strong i="11">@return</strong> \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        if (isset($row['rubrique'])) {
            $rubric = Rubric::firstOrCreate(['name' => $row['rubrique']]);
        } else {
            $rubric = Rubric::where('name', 'AUTRE')->first();
        }

        $area_id = intval(substr($row['code_postal'], 0, 2)) !== 0 ? intval(substr($row['code_postal'], 0, 2)) : 1;

        return new Contact([
            'name' => $row['nom'],
            'address' => $row['adresse'],
            'postal_code' => $row['code_postal'],
            'city' => $row['ville'],
            'phone_number' => $row['telephone'],
            'fax_number' => $row['fax'],
            'email' => $row['email'],
            'rubric_id' => $rubric->id,
            'area_id' => $area_id
        ]);
    }

    public function batchSize(): int
    {
        return 1000;
    }

    public function chunkSize(): int
    {
        return 1000;
    }
}
cannot-reproduce

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

temp_path(https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/config/excel.php#L28)๋ฅผ ์˜ˆ๋ฅผ ๋“ค์–ด ์ €์žฅ์†Œ ํด๋”๋กœ ๋ณ€๊ฒฝํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  21 ๋Œ“๊ธ€

์•ˆ๋…•ํ•˜์„ธ์š” @Mlouis ์ž…๋‹ˆ๋‹ค .

์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
Importable ํŠธ๋ ˆ์ž‡์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
(new ContactsImport)->queue('file.ext');

์ˆ˜์ž…ํ’ˆ ์ฐธ์กฐ

์ด ํ›„์—๋„ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์œผ๋ฉด ์ปจํŠธ๋กค๋Ÿฌ ์ฝ”๋“œ๋„ ๊ฒŒ์‹œํ•˜์‹ญ์‹œ์˜ค.

์•ˆ๋…•ํ•˜์„ธ์š” @GlennM๋‹˜ , ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๋‚ด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.

Excel::import(new ContactsImport, $request->file('liste'));
// and
(new ContactsImport)->queue($request->file('liste'));

๋˜ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์ถœํ•œ ํŒŒ์ผ์„ ContactsImport์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ๋จผ์ € ์ €์žฅํ•˜๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค.

$fileName = Str::uuid() . '.' . $request->file('liste')->getClientOriginalExtension();
$request->file('liste')->storeAs('listes', $fileName);
Excel::import(new ContactsImport, 'listes/' . $fileName);
// also tried with
(new ContactsImport)->queue('listes/' . $fileName);

ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. InvalidArgumentException: File "/tmp/whatever" does not exist. in /home/miguel/www/html/proliste/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:137

๋‚ด ๋ชฉ๋ก ์ปจํŠธ๋กค๋Ÿฌ:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Imports\ContactsImport;
use App\Exports\ContactsExport;
use App\Contact;
use App\Rubric;
use App\Area;
use App\Cart;
use Excel;
use DB;
use App\Http\Requests\ListRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class ListController extends Controller
{
    public function import(Request $request)
    {
        $request->validate([
            'liste' => 'required'
        ]);

        $fileName = Str::uuid() . '.' . $request->file('liste')->getClientOriginalExtension();
        $request->file('liste')->storeAs('listes', $fileName);

        (new ContactsImport)->queue('listes/' . $fileName);

        return back()->with('status', 'Liste ajoutรฉe avec succรจs');
    }
}

๋ถˆํ–‰ํžˆ๋„, ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

namespace App\Http\Controllers;

use Illuminate\Http\Request;

public function import(Request $request)
{
    (new ContactsImport)->queue($request->file('liste'));

    return back()->with('status', 'Liste ajoutรฉe avec succรจs');
}

์ฐธ๊ณ ๋กœ ์ €๋Š” ๋‹จ์ˆœํ™”๋œ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ œ ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

public function process(Request $request)
{
    (new UsersImport)->queue($request->file('dataset'));

    return back()->with('success', 'All good!');
}

๊ทธ๋ฆฌ๊ณ  ๋‚ด UsersImport ํด๋ž˜์Šค:

<?php

namespace App\Imports;

use App\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class UsersImport implements ToModel, WithHeadingRow, WithBatchInserts, WithChunkReading, ShouldQueue
{
    use Importable;

    /**
    * <strong i="13">@param</strong> array $row
    *
    * <strong i="14">@return</strong> \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new User([
            'name' => $row['name'],
            'email' => $row['email'],
            'password' => $row['id'],
        ]);
    }

    /**
     * <strong i="15">@return</strong> int
     */
    public function batchSize(): int
    {
        return 1000;
    }

    /**
     * <strong i="16">@return</strong> int
     */
    public function chunkSize(): int
    {
        return 1000;
    }
}

I๋Š” ์ถ”๊ฐ€ / ์ œ๊ฑฐ ์‹œ๋„ WithHeadingRow , WithBatchInserts , WithChunkReading , Importable ์‚ฌ์šฉ ToCollection ๋Œ€์‹  ToModel ์„ฑ๊ณตํ•˜์ง€ . ์ž‘์—…์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์ง€ ์•Š์„ ๋•Œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—…์œผ๋กœ ๋ชฉ๋ก์„ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์œผ๋ฉฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋งŒ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๊ฐ€ ๋‚ด dev ์„œ๋ฒ„์˜ ์ž˜๋ชป๋œ ๊ตฌ์„ฑ์—์„œ ๋น„๋กฏ๋œ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

๋ฌธ์ œ๊ฐ€ ๋‚ด dev ์„œ๋ฒ„์˜ ์ž˜๋ชป๋œ ๊ตฌ์„ฑ์—์„œ ๋น„๋กฏ๋œ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

์‹ค์ œ๋กœ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
PHP 7.1 / Laravel 5.6 ๋ฐ PHP 7.2 / Laravel 5.7์—์„œ ํ…Œ์ŠคํŠธํ–ˆ์œผ๋ฉฐ T oModel , WithHeadingRow , WithBatchInserts , WithChunkReading ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค ShouldQueue ๋ฐ Importable

์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์ƒ์—…์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ •๊ตํ•œ ์ง€์›์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ๊ธด๊ธ‰ํ•˜๊ฒŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ƒ์—…์ ์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ง€์› ํŽ˜์ด์ง€๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋‚ด๊ฐ€ ์„ ๋‘์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 150,000๊ฐœ ์ด์ƒ์˜ ํ–‰์„ ๋Œ€๊ธฐ ์ค‘์ธ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์‹œ๋„ํ•œ ํ›„ ์ž‘์—…์ด ์‹คํŒจํ•˜์—ฌ ๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ 20๊ฐœ์˜ AppendQueryToSheet ์ž‘์—… ํ›„์— ๊ฐ€์ ธ์˜ค๊ธฐ์™€ ๊ฐ™์ด ์ฆ‰์‹œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ํฌ๊ธฐ ์ œํ•œ๊ณผ ๊ฐ™์ด ๋‚ด /tmp ํด๋”์— ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” Debian 9๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ / ( /tmp ), /home ๋ฐ swap , ์ด๊ฒƒ์€ ํŒŒํ‹ฐ์…˜ ํฌ๊ธฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ํ•œ๊ณ„.

๋ญ”๊ฐ€ ์ฐพ์œผ๋ฉด ์—…๋ฐ์ดํŠธ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! :๊ธฐ๋„ํ•˜๋‹ค:

__ํŽธ์ง‘ํ•˜๋‹ค__
์ด ๋ฌธ์ œ์˜ ์ด๋ฆ„์„ [BUG] ๋Œ€์‹  [QUESTION]์œผ๋กœ ๋ฐ”๊ฟ”์•ผ ํ•ฉ๋‹ˆ๊นŒ?

temp_path(https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/config/excel.php#L28)๋ฅผ ์˜ˆ๋ฅผ ๋“ค์–ด ์ €์žฅ์†Œ ํด๋”๋กœ ๋ณ€๊ฒฝํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@patrickbrouwers ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํฐ ํŒŒ์ผ์„ ์˜ค๋ฅ˜ ์—†์ด ๊ฐ€์ ธ์˜ค๊ณ  ๋‚ด๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

@patrickbrowwers ๊ตฌ์„ฑ ์—‘์…€์— temp_path๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ž์„ธํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@sharjeelz ์ตœ์‹  ๋ฒ„์ „์˜ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/config/excel.php#L167 ํ˜„์žฌ ์ด์ „ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ temp_path์— ๋Œ€ํ•œ ๋Œ€์ฒด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ์ด๊ฒƒ์ด ์˜ค๋ž˜๋œ ๋ฌธ์ œ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๋งค์šฐ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ œ ๋™๋ฃŒ์™€ ์ €๋Š” ๋™์ผํ•œ ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋Š”๋ฐ "ํŒŒ์ผ X๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค"๋ผ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๊ณ  ๊ทธ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ config/local_path๋ฅผ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์•Œ๋ ค์ง„ ๋ฌธ์ œ๋ฅผ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋‘˜ ๋‹ค Macbook์—์„œ ๋กœ์ปฌ๋กœ Laravel ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  lib ๋ฒ„์ „ 3.1.17์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒŒ์ผ ์ด๋ฆ„ C:UsersAshimAppDataLocalTemplaravel-excel-K6OeXpSQuAARlI0UrSeOAkFZ0kELq0Ax.xls๊ฐ€ OLE ํŒŒ์ผ๋กœ ์ธ์‹๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋„ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ์ง€๋งŒ ์ œ ์งˆ๋ฌธ์€: ๊ฐ€์ ธ์˜ค๊ธฐ ๊ธฐ๋Šฅ์—์„œ ๋ณด๋‚ธ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ๋‹ค๋ฅธ ํŒŒ์ผ ์ด๋ฆ„์ด ํ‘œ์‹œ๋˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ •๋ณด๋ฅผ ์ฝ๋Š” ์ž„์‹œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๊นŒ?

````
[2020-04-17 15:15:26] local.ERROR: ํŒŒ์ผ "/tmp/laravel-excel-rKsJKI2Clu2sEV3OqMtPngacRRZd8iJM.xlsx"๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. {"์˜ˆ์™ธ":"[๊ฐ์ฒด] (InvalidArgumentException(์ฝ”๋“œ: 0): ํŒŒ์ผ "/tmp/laravel-excel-rKsJKI2Clu2sEV3OqMtPngacRRZd8iJM.xlsx"๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. /var/www/html/sites/dashboard-imprensa/vendor/ phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:137)
[์Šคํƒ ์ถ”์ ]

0 /var/www/html/sites/dashboard-imprensa/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php(327): PhpOffice\PhpSpreadsheet\Shared\File::assertFile('/tmp/laravel- ์ „...')

1 /var/www/html/sites/dashboard-imprensa/vendor/maatwebsite/excel/src/Jobs/ReadChunk.php(118): PhpOffice\PhpSpreadsheet\Reader\Xlsx->load('/tmp/laravel-ex. ..')

2 [๋‚ด๋ถ€ ํ•จ์ˆ˜]: Maatwebsite\Excel\Jobs\ReadChunk->handle(Object(Maatwebsite\Excel\Transactions\DbTransactionHandler))

3 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(32): call_user_func_array(๋ฐฐ์—ด, ๋ฐฐ์—ด)

4 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{ํด๋กœ์ €}()

5 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(90): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))

6 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(34): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application) , ๋ฐฐ์—ด, ๊ฐ์ฒด(ํด๋กœ์ €))

7 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/Container.php(592): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application) , ๋ฐฐ์—ด, ๋ฐฐ์—ด, NULL)

8 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(94): Illuminate\Container\Container->call(Array)

9 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object( Maatwebsite\Excel\Jobs\ReadChunk))

10 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object( Maatwebsite\Excel\Jobs\ReadChunk))

11 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure))

12 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(83): Illuminate\Bus\Dispatcher->dispatchNow(Object(Maatwebsite\Excel\Jobs\ ReadChunk), ๊ฑฐ์ง“)

13 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Queue\CallQueuedHandler->Illuminate\Queue\{ํด๋กœ์ €}(Object( Maatwebsite\Excel\Jobs\ReadChunk))

14 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object( Maatwebsite\Excel\Jobs\ReadChunk))

15 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(85): Illuminate\Pipeline\Pipeline->then(Object(Closure))

16 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(59): Illuminate\Queue\CallQueuedHandler->dispatchThroughMiddleware(Object(Illuminate\Queue\Jobs\ DatabaseJob), ๊ฐœ์ฒด(Maatwebsite\Excel\Jobs\ReadChunk))

17 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(98): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\ Jobs\DatabaseJob), ๋ฐฐ์—ด)

18 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(356): Illuminate\Queue\Jobs\Job->fire()

19 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(306): Illuminate\Queue\Worker->process('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค', Object(Illuminate\ Queue\Jobs\DatabaseJob), ๊ฐœ์ฒด(Illuminate\Queue\WorkerOptions))

20 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(132): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\ DatabaseJob), '๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค', ๊ฐœ์ฒด(Illuminate\Queue\WorkerOptions))

21 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(112): Illuminate\Queue\Worker->daemon('database', 'default ', ๊ฐœ์ฒด(Illuminate\Queue\WorkerOptions))

22 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand->runWorker('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค', '๊ธฐ๋ณธ')

23 [๋‚ด๋ถ€ ํ•จ์ˆ˜]: Illuminate\Queue\Console\WorkCommand->handle()

24 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(32): call_user_func_array(๋ฐฐ์—ด, ๋ฐฐ์—ด)

25 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{ํด๋กœ์ €}()

26 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(90): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))

27 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(34): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application) , ๋ฐฐ์—ด, ๊ฐ์ฒด(ํด๋กœ์ €))

28 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Container/Container.php(592): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application) , ๋ฐฐ์—ด, ๋ฐฐ์—ด, NULL)

29 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Console/Command.php(134): Illuminate\Container\Container->call(Array)

30 /var/www/html/sites/dashboard-imprensa/vendor/symfony/console/Command/Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput) , ๊ฐœ์ฒด(Illuminate\Console\OutputStyle))

31 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\Component\Console\Command\Command->run(Object(Symfony\ Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))

32 /var/www/html/sites/dashboard-imprensa/vendor/symfony/console/Application.php(912): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), ๊ฐœ์ฒด (Symfony\Component\Console\Output\ConsoleOutput))

33 /var/www/html/sites/dashboard-imprensa/vendor/symfony/console/Application.php(264): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), ๊ฐœ์ฒด (Symfony\Component\Console\Input\ArgvInput), ๊ฐœ์ฒด(Symfony\Component\Console\Output\ConsoleOutput))

34 /var/www/html/sites/dashboard-imprensa/vendor/symfony/console/Application.php(140): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput) , ๊ฐœ์ฒด(Symfony\Component\Console\Output\ConsoleOutput))

35 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\) Console\Input\ArgvInput), ๊ฐœ์ฒด(Symfony\Component\Console\Output\ConsoleOutput))

36 /var/www/html/sites/dashboard-imprensa/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(130): Illuminate\Console\Application->run(Object(Symfony\Component\ Console\Input\ArgvInput), ๊ฐœ์ฒด(Symfony\Component\Console\Output\ConsoleOutput))

37 /var/www/html/sites/dashboard-imprensa/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console) \์ถœ๋ ฅ\์ฝ˜์†”์ถœ๋ ฅ))

38 {๋ฉ”์ธ}

"}
````

์ด๊ฒƒ์€ ๋‚ด๊ฐ€๋ฐ›๋Š” ์˜ค๋ฅ˜์ด์ง€๋งŒ ๋‚ด๊ฐ€ ๋ณด๋‚ธ ํŒŒ์ผ์€ 'temp/12020-04.xlsx'์˜€์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์ด ํŒŒ์ผ์„ ์ˆ˜์‹ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์ด๋ฏธ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž„์‹œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋‹ค๋ฅธ ์ž„์‹œ ํด๋”๋ฅผ ์„ค์ •ํ•ด ๋ณด์‹ญ์‹œ์˜ค https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/config/excel.php#L166

์•ˆ๋…•ํ•˜์„ธ์š” @patrickbrouwers๋‹˜ , ๋น ๋ฅธ ๋‹ต๋ณ€์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ๋‚ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค :(

$header = (new HeadingRowImport)->toArray($request->file('arquivo'))[0][0];

$file = Storage::putFileAs(
    'temp',
    $request->file('arquivo'),
    $request->input('dashboard_id') . str_replace("/", "-", $request->input('ano_mes')) . '.' . pathinfo($request->file('arquivo')->getClientOriginalName())['extension']
);

if ($request->input('acao') == "import") {
    Excel::import((new DadosImport($request->input('ano_mes'), $request->input('dashboard_id'), $header, $file, true)), $file);
} else {
    Excel::import((new DadosImport($request->input('ano_mes'), $request->input('dashboard_id'), $header, $file)), $file);
}

์ด๊ฒƒ์€ ๋‚ด ๊ฐ€์ ธ์˜ค๊ธฐ ๊ธฐ๋Šฅ์ด๋ฉฐ ๊ฝค ํ‘œ์ค€์ ์ž…๋‹ˆ๋‹ค. ํŒŒ์ผ์€ ์˜ค๋ฅธ์ชฝ ํด๋”์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ public_path($file)๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ์ž„์‹œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๊นŒ?

ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋ชจ๋“  ๊ฒƒ์„ ๋‹ค์‹œ ์„ค์น˜ํ–ˆ๋Š”๋ฐ ์ด์ œ ๋ชจ๋‘ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Excel ๋‚ด๋ณด๋‚ด๊ธฐ์— ๋Œ€๊ธฐ์—ด ์ž‘์—…์„ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์˜ˆ์™ธ๊ฐ€ ํ‘œ์‹œ๋˜์–ด ์ž‘์—…์„ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ErrorException: fopen(/var/www/html/biomaze.ir/storage/framework/laravel-excel/laravel-excel-85fvUcwqDwshFsD4o5PWwtamG83wnzG6): ์ŠคํŠธ๋ฆผ์„ ์—ด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค: /var/www/html/biomaze.ir/vendor์—์„œ ๊ถŒํ•œ์ด ๊ฑฐ๋ถ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. /phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/BaseWriter. PHP:111

๋„์™€์ฃผ์„ธ์š”?์ œ๋ฐœ

storage ์— ๋Œ€ํ•œ ์†Œ์œ ์ž ๋ฐ ๊ถŒํ•œ์„ ๋ณ€๊ฒฝํ•ด ๋ณด์‹ญ์‹œ์˜ค.
sudo chown -R www-data:<your_username> storage/ && sudo chmod -R g+w storage/

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํ™ˆ์Šคํ…Œ๋“œ ๋‚ด์—์„œ dev ํ™˜๊ฒฝ์„ ์‹คํ–‰ ์ค‘์ด๋ฉด ์ž„์‹œ ํŒŒ์ผ์ด ์ž˜ ์ƒ์„ฑ๋˜์ง€๋งŒ(์•ฑ์—์„œ ์—…๋กœ๋“œ๋œ csv๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Œ) phpspreadsheet๋Š” ๋Œ€๊ธฐ์—ด ๋‚ด์—์„œ ์‹คํ–‰ํ•  ๋•Œ ํŒŒ์ผ์„ ์ฐพ๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

InvalidArgumentException {#1344 #message: "File "/home/vagrant/code/storage/app/data-imports/laravel-excel-YNpPHnBtKZXaXKIbR68goCYM5qLlzUxt.csv" does not exist." #code: 0 #file: "./vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php" #line: 135

๋Œ€๊ธฐ์—ด์€ ์ดˆ๊ธฐ ReadChunk ์ž‘์—…์„ ์ง€๋‚˜์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. tinker๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ด ๊ฒฝ๋กœ์—์„œ file_exists()๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ ์ด๊ฒƒ์„ ์ง๋ฉดํ•˜๊ณ  ํ•ด๊ฒฐ ํ–ˆ์Šต๋‹ˆ๊นŒ?

๋”ฐ๋ผ์„œ ๋ฌธ์ œ๋Š” ๋ฐฉ๋ž‘์ž์˜ ์™ธ๋ถ€์—์„œ ์‹คํ–‰๋˜๋Š” queue:listen ๋ช…๋ น์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด vagrant ๋‚ด์—์„œ ํ ์ž‘์—…์ž๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฉ๋ž‘์ž SSH
CD ์ฝ”๋“œ
PHP ์žฅ์ธ ๋Œ€๊ธฐ์—ด:๋“ฃ๊ธฐ

๋‹ฌ์ฝคํ•œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/config/excel.php#L166

๋‹ค๋ฅธ ํด๋” @patrickbrowers๋ฅผ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ๋‚ด ๊ตฌ์„ฑ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

`<?php

use Maatwebsite\Excel\Excel;

return [
    'exports' => [

    /*
    |--------------------------------------------------------------------------
    | Chunk size
    |--------------------------------------------------------------------------
    |
    | When using FromQuery, the query is automatically chunked.
    | Here you can specify how big the chunk should be.
    |
    */
    'chunk_size'             => 1000,

    /*
    |--------------------------------------------------------------------------
    | Pre-calculate formulas during export
    |--------------------------------------------------------------------------
    */
    'pre_calculate_formulas' => false,

    /*
    |--------------------------------------------------------------------------
    | Enable strict null comparison
    |--------------------------------------------------------------------------
    |
    | When enabling strict null comparison empty cells ('') will
    | be added to the sheet.
    */
    'strict_null_comparison' => false,

    /*
    |--------------------------------------------------------------------------
    | CSV Settings
    |--------------------------------------------------------------------------
    |
    | Configure e.g. delimiter, enclosure and line ending for CSV exports.
    |
    */
    'csv'                    => [
        'delimiter'              => ',',
        'enclosure'              => '"',
        'line_ending'            => PHP_EOL,
        'use_bom'                => false,
        'include_separator_line' => false,
        'excel_compatibility'    => false,
    ],

    /*
    |--------------------------------------------------------------------------
    | Worksheet properties
    |--------------------------------------------------------------------------
    |
    | Configure e.g. default title, creator, subject,...
    |
    */
    'properties'             => [
        'creator'        => '',
        'lastModifiedBy' => '',
        'title'          => '',
        'description'    => '',
        'subject'        => '',
        'keywords'       => '',
        'category'       => '',
        'manager'        => '',
        'company'        => '',
    ],
],

'imports'            => [

    /*
    |--------------------------------------------------------------------------
    | Read Only
    |--------------------------------------------------------------------------
    |
    | When dealing with imports, you might only be interested in the
    | data that the sheet exists. By default we ignore all styles,
    | however if you want to do some logic based on style data
    | you can enable it by setting read_only to false.
    |
    */
    'read_only' => true,

    /*
    |--------------------------------------------------------------------------
    | Ignore Empty
    |--------------------------------------------------------------------------
    |
    | When dealing with imports, you might be interested in ignoring
    | rows that have null values or empty strings. By default rows
    | containing empty strings or empty values are not ignored but can be
    | ignored by enabling the setting ignore_empty to true.
    |
    */
    'ignore_empty' => false,

    /*
    |--------------------------------------------------------------------------
    | Heading Row Formatter
    |--------------------------------------------------------------------------
    |
    | Configure the heading row formatter.
    | Available options: none|slug|custom
    |
    */
    'heading_row' => [
        'formatter' => 'slug',
    ],

    /*
    |--------------------------------------------------------------------------
    | CSV Settings
    |--------------------------------------------------------------------------
    |
    | Configure e.g. delimiter, enclosure and line ending for CSV imports.
    |
    */
    'csv'         => [
        'delimiter'        => ',',
        'enclosure'        => '"',
        'escape_character' => '\\',
        'contiguous'       => false,
        'input_encoding'   => 'UTF-8',
    ],

    /*
    |--------------------------------------------------------------------------
    | Worksheet properties
    |--------------------------------------------------------------------------
    |
    | Configure e.g. default title, creator, subject,...
    |
    */
    'properties'  => [
        'creator'        => '',
        'lastModifiedBy' => '',
        'title'          => '',
        'description'    => '',
        'subject'        => '',
        'keywords'       => '',
        'category'       => '',
        'manager'        => '',
        'company'        => '',
    ],

],

/*
|--------------------------------------------------------------------------
| Extension detector
|--------------------------------------------------------------------------
|
| Configure here which writer/reader type should be used when the package
| needs to guess the correct type based on the extension alone.
|
*/
'extension_detector' => [
    'xlsx'     => Excel::XLSX,
    'xlsm'     => Excel::XLSX,
    'xltx'     => Excel::XLSX,
    'xltm'     => Excel::XLSX,
    'xls'      => Excel::XLS,
    'xlt'      => Excel::XLS,
    'ods'      => Excel::ODS,
    'ots'      => Excel::ODS,
    'slk'      => Excel::SLK,
    'xml'      => Excel::XML,
    'gnumeric' => Excel::GNUMERIC,
    'htm'      => Excel::HTML,
    'html'     => Excel::HTML,
    'csv'      => Excel::CSV,
    'tsv'      => Excel::TSV,

    /*
    |--------------------------------------------------------------------------
    | PDF Extension
    |--------------------------------------------------------------------------
    |
    | Configure here which Pdf driver should be used by default.
    | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF
    |
    */
    'pdf'      => Excel::DOMPDF,
],

/*
|--------------------------------------------------------------------------
| Value Binder
|--------------------------------------------------------------------------
|
| PhpSpreadsheet offers a way to hook into the process of a value being
| written to a cell. In there some assumptions are made on how the
| value should be formatted. If you want to change those defaults,
| you can implement your own default value binder.
|
| Possible value binders:
|
| [x] Maatwebsite\Excel\DefaultValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class
|
*/
'value_binder' => [
    'default' => Maatwebsite\Excel\DefaultValueBinder::class,
],

'cache' => [
    /*
    |--------------------------------------------------------------------------
    | Default cell caching driver
    |--------------------------------------------------------------------------
    |
    | By default PhpSpreadsheet keeps all cell values in memory, however when
    | dealing with large files, this might result into memory issues. If you
    | want to mitigate that, you can configure a cell caching driver here.
    | When using the illuminate driver, it will store each value in a the
    | cache store. This can slow down the process, because it needs to
    | store each value. You can use the "batch" store if you want to
    | only persist to the store when the memory limit is reached.
    |
    | Drivers: memory|illuminate|batch
    |
    */
    'driver'     => 'memory',

    /*
    |--------------------------------------------------------------------------
    | Batch memory caching
    |--------------------------------------------------------------------------
    |
    | When dealing with the "batch" caching driver, it will only
    | persist to the store when the memory limit is reached.
    | Here you can tweak the memory limit to your liking.
    |
    */
    'batch'     => [
        'memory_limit' => 60000,
    ],

    /*
    |--------------------------------------------------------------------------
    | Illuminate cache
    |--------------------------------------------------------------------------
    |
    | When using the "illuminate" caching driver, it will automatically use
    | your default cache store. However if you prefer to have the cell
    | cache on a separate store, you can configure the store name here.
    | You can use any store defined in your cache config. When leaving
    | at "null" it will use the default store.
    |
    */
    'illuminate' => [
        'store' => null,
    ],
],

/*
|--------------------------------------------------------------------------
| Transaction Handler
|--------------------------------------------------------------------------
|
| By default the import is wrapped in a transaction. This is useful
| for when an import may fail and you want to retry it. With the
| transactions, the previous import gets rolled-back.
|
| You can disable the transaction handler by setting this to null.
| Or you can choose a custom made transaction handler here.
|
| Supported handlers: null|db
|
*/
'transactions' => [
    'handler' => 'db',
],

'temporary_files' => [

    /*
    |--------------------------------------------------------------------------
    | Local Temporary Path
    |--------------------------------------------------------------------------
    |
    | When exporting and importing files, we use a temporary file, before
    | storing reading or downloading. Here you can customize that path.
    |
    */
    'local_path'          => storage_path('framework/laravel-excel'),

    /*
    |--------------------------------------------------------------------------
    | Remote Temporary Disk
    |--------------------------------------------------------------------------
    |
    | When dealing with a multi server setup with queues in which you
    | cannot rely on having a shared local temporary path, you might
    | want to store the temporary file on a shared disk. During the
    | queue executing, we'll retrieve the temporary file from that
    | location instead. When left to null, it will always use
    | the local path. This setting only has effect when using
    | in conjunction with queued imports and exports.
    |
    */
    'remote_disk'         => null,
    'remote_prefix'       => null,

    /*
    |--------------------------------------------------------------------------
    | Force Resync
    |--------------------------------------------------------------------------
    |
    | When dealing with a multi server setup as above, it's possible
    | for the clean up that occurs after entire queue has been run to only
    | cleanup the server that the last AfterImportJob runs on. The rest of the server
    | would still have the local temporary file stored on it. In this case your
    | local storage limits can be exceeded and future imports won't be processed.
    | To mitigate this you can set this config value to be true, so that after every
    | queued chunk is processed the local temporary file is deleted on the server that
    | processed it.
    |
    */
    'force_resync_remote' => null,
    ],
];

`

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰