Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Background Error SplFileInfo::getSize(): stat failed for xxx #3888

Closed
1 task done
sluxzer opened this issue Mar 6, 2023 · 3 comments
Closed
1 task done

[Bug]: Background Error SplFileInfo::getSize(): stat failed for xxx #3888

sluxzer opened this issue Mar 6, 2023 · 3 comments
Labels

Comments

@sluxzer
Copy link

sluxzer commented Mar 6, 2023

Is the bug applicable and reproducable to the latest version of the package and hasn't it been reported before?

  • Yes, it's still reproducable

What version of Laravel Excel are you using?

3.1.45

What version of Laravel are you using?

Lumen 6.3.3

What version of PHP are you using?

7.4.28

Describe your issue

Hi there,

This issue has already been submitted multiple times, but it seems it was abandoned in the closed thread, and pardon me for creating a new ticket. I've been using this package for 5 years, I hope I can help with the issue.

I got this issue on the lumen framework, actually, it's not breaking the download process, rather it only throws an output error on the storage/logs folder.

I got several results from this error, and I'm not sure it's all related:

  1. File was successfully downloaded, and I can open the file normally
  2. File was successfully downloaded, but when I open the file, it somehow corrupted (intermittent)
    image
  3. The result1-2 is if I'm using format .xlxs but if I'm using format .csv the error is printed on the file itself. I'm guessing this is connected with the second problem.
    image

My Guessing:
When the download process begins, I try to check on var/app/storage/framework/cache/laravel-excel/ but no file is generated, I try to delete the laravel-excel folder, and It automatically created a new folder but it still empty. I think the error happened because the SplFileInfo::getSize(): read an undefined file.

Here is the permission for folder laravel-excel, I think you'd like the screenshot
image

Here is the full log:

[2023-03-06 08:11:39] local.ERROR: SplFileInfo::getSize(): stat failed for /var/app/storage/framework/cache/laravel-excel/laravel-excel-qeT8Enpg54NpnZ9V3as7IeRa31899Uek.csv {"user-agent":"GuzzleHttp/7","url":"http://localhost/download","input":{"month":"03","year":"2023","page":"1"},"userId":1811,"exception":"[object] (RuntimeException(code: 0): SplFileInfo::getSize(): stat failed for /var/app/storage/framework/cache/laravel-excel/laravel-excel-qeT8Enpg54NpnZ9V3as7IeRa31899Uek.csv at /var/app/vendor/symfony/http-foundation/BinaryFileResponse.php:200)
[stacktrace]
#0 /var/app/vendor/symfony/http-foundation/BinaryFileResponse.php(200): SplFileInfo->getSize()
#1 /var/app/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(438): Symfony\Component\HttpFoundation\BinaryFileResponse->prepare(Object(Illuminate\Http\Request))
#2 /var/app/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(133): Laravel\Lumen\Application->prepareResponse(Object(Symfony\Component\HttpFoundation\BinaryFileResponse))
#3 /var/app/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(117): Laravel\Lumen\Application->callTerminableMiddleware(Object(Symfony\Component\HttpFoundation\BinaryFileResponse))
#4 /var/app/public/index.php(28): Laravel\Lumen\Application->run()
#5 {main}
"}

How can the issue be reproduced?

I never reproduce this in another environment, but I think my code was simply enough

TicketExport.php

<?php

namespace Exports;

use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class TicketExport implements FromArray, WithHeadings, WithMapping, ShouldAutoSize, WithStyles
{
    use Exportable;

    protected $tickets;

    public function __construct(array $tickets)
    {
        $this->tickets = $tickets;
    }
    
    public function styles(Worksheet $sheet)
    {
        $sheet->getStyle('A1:G1')->getFont()->setBold(true);
        $sheet->getStyle('A1:G1')->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB('C5D9F1');
    }


    public function array(): array
    {
        return $this->tickets;
    }

    public function headings(): array
    {
        return [
            'ID',
            'Patient Name',
            'Clinic Name',
            'Approved Date',
            'Deadline Date',
            'Completed Date',
            'Notes',
        ];
    }

    public function map($tickets): array
    {

        return [
            $tickets['id'],
            $tickets['name'],
            $tickets['clinic'],
            $tickets['approved_date'],
            $tickets['deadline_date'],
            $tickets['completed_date'],
            $tickets['notes'],
        ];
    }
}

My Controller:

    public function download(Request $request)
    {
        $this->validate($request, [
            'month' => 'required',
            'year' => 'required',
        ]);

        $ticket = $this->service->getDownloadList($request);
        
        return (new ProductionTicketExport($productionTicket))->download("Ticket $request->month-$request->year.xlsx", \Maatwebsite\Excel\Excel::XLSX);
    }

What should be the expected behaviour?

I expect no error thrown after downloading the file

@sluxzer sluxzer added the bug label Mar 6, 2023
@patrickbrouwers
Copy link
Member

Looks like your api response is outputting to the buffer. As you are using download, everything is prepended to that output-buffer. https://www.php.net/manual/en/function.ob-clean.php

@sluxzer
Copy link
Author

sluxzer commented Mar 29, 2023

Hey @patrickbrouwers, I think your statement about API response is correct because mainly my project is API, so every response must return the object.

However, after implementing Laravel-Excel, I custom the response to make it able to download files with this custom middleware

<?php

namespace Core\Middleware;

use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use NbsPhp\Core\Interfaces\ResponseMapperInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ResponseMiddleware
{
    protected $responseMapper;

    public function __construct(ResponseMapperInterface $responseMapper)
    {
        $this->responseMapper = $responseMapper;
    }

    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        if ($response instanceof BinaryFileResponse) {
            return $response;
        }
        if ($response instanceof StreamedResponse) {
            return $response;
        }
        if ($response->original instanceof View) {
            return $response;
        }
        if (isset($response->exception) || ($response instanceof JsonResponse && $response->getStatusCode() == Response::HTTP_UNPROCESSABLE_ENTITY)) {
            return $this->responseMapper->errorResponse($response);
        }

        return $this->responseMapper->successResponse($response);
    }
}

As you can see, I add this line so the response be able to download file

      if ($response instanceof BinaryFileResponse) {
            return $response;
        }

fyi, I tried adding ob_clean() or ob_end_clean() in the above middleware or below controller, but the error still occurs

 public function download(Request $request)
    {
        $this->validate($request, [
            'month' => 'required',
            'year' => 'required',
        ]);

        $productionTicket = $this->service->getDownloadList($request);
        
        **ob_clean();** // @patrickbrouwers here is the function

        return Excel::download(new ProductionTicketExport($productionTicket), "KLAR Production Ticket $request->month-$request->year.xlsx", \Maatwebsite\Excel\Excel::XLSX);
    }

Is that the correct implementation? or did I miss something?

@sluxzer
Copy link
Author

sluxzer commented Mar 29, 2023

However, I tried your solution in #2281 (comment)

by adding function ->deleteFileAfterSend(false); and the error is gone.

But I am still curious, as to why there is no excel file in my temp folder at var/app/storage/framework/cache/laravel-excel/ , because I believe this issue occurs because the function failed to create a file at the above temp folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants