Laravel-Excel: [BUG] Export to s3 - CouldNotCreateChecksumException

Prerequisites

  • Able to reproduce the behaviour outside of your code, the problem is isolated to Laravel Excel.
  • Checked that your issue isn’t already filed.
  • Checked if no PR was submitted that fixes this problem.

Versions

  • PHP version: 7.2.0-1+ubuntu16.04.1+deb.sury.org+1
  • Laravel version: 5.8.10
  • Package version: 3.1.11

Description

Upgrading from laravel 5.7 to 5.8 went through the normal upgrade steps. Got all code in the framework updated based on the laravel docs. Started testing and realized exporting data and storing it in s3 was failing.

Steps to Reproduce

Expected behavior:

The file should be exported and stored in s3 like it is in the previous version before upgrading the framework and laravel excel

Actual behavior:

The exception occurs with queuing and regular “store” methods. I get the following error:

A sha256 checksum could not be calculated for the provided upload body, because it was not seekable. To prevent this error you can either 1) include the ContentMD5 or ContentSHA256 parameters with your request, 2) use a seekable stream for the body, or 3) wrap the non-seekable stream in a GuzzleHttp\Psr7\CachingStream object. You should be careful though and remember that the CachingStream utilizes PHP temp streams. This means that the stream will be temporarily stored on the local disk.

(2/2) CouldNotCreateChecksumException A sha256 checksum could not be calculated for the provided upload body, because it was not seekable. To prevent this error you can either 1) include the ContentMD5 or ContentSHA256 parameters with your request, 2) use a seekable stream for the body, or 3) wrap the non-seekable stream in a GuzzleHttp\Psr7\CachingStream object. You should be careful though and remember that the CachingStream utilizes PHP temp streams. This means that the stream will be temporarily stored on the local disk. in SignatureV4.php line 166 at SignatureV4->getPayload(object(Request))in S3SignatureV4.php line 22 at S3SignatureV4->signRequest(object(Request), object(Credentials))in Middleware.php line 126 at Middleware::Aws{closure}(object(Credentials))in FulfilledPromise.php line 39 at FulfilledPromise::GuzzleHttp\Promise{closure}()in TaskQueue.php line 47 at TaskQueue->run(true)in Promise.php line 246 at Promise->invokeWaitFn()in Promise.php line 223 at Promise->waitIfPending()in Promise.php line 267 at Promise->invokeWaitList()in Promise.php line 225 at Promise->waitIfPending()in Promise.php line 62 at Promise->wait()in S3ClientTrait.php line 33 at S3Client->upload(‘mobiniti-uploads’, ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, ‘public-read’, array(‘params’ =>array(‘visibility’ => ‘public’, ‘ACL’ => ‘public-read’, ‘ContentType’ => ‘text/x-comma-separated-values’, ‘ContentLength’ => 172)))in AwsS3Adapter.php line 596 at AwsS3Adapter->upload(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in AwsS3Adapter.php line 380 at AwsS3Adapter->writeStream(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in Filesystem.php line 122 at Filesystem->putStream(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in FilesystemAdapter.php line 194 at FilesystemAdapter->put(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, array())in Disk.php line 61 at Disk->put(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource)in Disk.php line 82 at Disk->copy(object(LocalTemporaryFile), ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’)in Excel.php line 102 at Excel->store(object(Unsubscribes), ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, ‘s3’, ‘Csv’, array())in Exportable.php line 52 at Unsubscribes->store(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, ‘s3’, ‘Csv’)in Export.php line 72 at Export->exportUnsubscribes()in DashboardController.php line 270 at DashboardController->exportUnsubscribes() at call_user_func_array(array(object(DashboardController), ‘exportUnsubscribes’), array())in Controller.php line 54 at Controller->callAction(‘exportUnsubscribes’, array())in ControllerDispatcher.php line 45 at ControllerDispatcher->dispatch(object(Route), object(DashboardController), ‘exportUnsubscribes’)in Route.php line 219 at Route->runController()in Route.php line 176 at Route->run()in Router.php line 680 at Router->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 30 at Pipeline->Illuminate\Routing{closure}(object(Request))in MainController.php line 49 at MainController->App\Http\Controllers\App{closure}(object(Request), object(Closure))in Pipeline.php line 145 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in VerifyCsrfToken.php line 22 at VerifyCsrfToken->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AppAuthentication.php line 61 at AppAuthentication->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in TrustProxies.php line 57 at TrustProxies->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AccountHostnameMiddleware.php line 21 at AccountHostnameMiddleware->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in CreateFreshApiToken.php line 50 at CreateFreshApiToken->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in SubstituteBindings.php line 41 at SubstituteBindings->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AuthenticateSession.php line 58 at AuthenticateSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in ShareErrorsFromSession.php line 49 at ShareErrorsFromSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in StartSession.php line 56 at StartSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AddQueuedCookiesToResponse.php line 37 at AddQueuedCookiesToResponse->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in EncryptCookies.php line 66 at EncryptCookies->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 104 at Pipeline->then(object(Closure))in Router.php line 682 at Router->runRouteWithinStack(object(Route), object(Request))in Router.php line 657 at Router->runRoute(object(Request), object(Route))in Router.php line 623 at Router->dispatchToRoute(object(Request))in Router.php line 612 at Router->dispatch(object(Request))in Kernel.php line 176 at Kernel->Illuminate\Foundation\Http{closure}(object(Request))in Pipeline.php line 30 at Pipeline->Illuminate\Routing{closure}(object(Request))in ServeNova.php line 26 at ServeNova->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in InjectDebugbar.php line 58 at InjectDebugbar->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in CheckForMaintenanceMode.php line 62 at CheckForMaintenanceMode->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 104 at Pipeline->then(object(Closure))in Kernel.php line 151 at Kernel->sendRequestThroughRouter(object(Request))in Kernel.php line 116 at Kernel->handle(object(Request))in index.php line 52

(1/2) RuntimeExceptionCannot read from non-readable stream in Stream.php line 208 at Stream->read(1048576)in functions.php line 419 at GuzzleHttp\Psr7\hash(object(Stream), ‘sha256’)in SignatureV4.php line 164 at SignatureV4->getPayload(object(Request))in S3SignatureV4.php line 22 at S3SignatureV4->signRequest(object(Request), object(Credentials))in Middleware.php line 126 at Middleware::Aws{closure}(object(Credentials))in FulfilledPromise.php line 39 at FulfilledPromise::GuzzleHttp\Promise{closure}()in TaskQueue.php line 47 at TaskQueue->run(true)in Promise.php line 246 at Promise->invokeWaitFn()in Promise.php line 223 at Promise->waitIfPending()in Promise.php line 267 at Promise->invokeWaitList()in Promise.php line 225 at Promise->waitIfPending()in Promise.php line 62 at Promise->wait()in S3ClientTrait.php line 33 at S3Client->upload(‘mobiniti-uploads’, ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, ‘public-read’, array(‘params’ =>array(‘visibility’ => ‘public’, ‘ACL’ => ‘public-read’, ‘ContentType’ => ‘text/x-comma-separated-values’, ‘ContentLength’ => 172)))in AwsS3Adapter.php line 596 at AwsS3Adapter->upload(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in AwsS3Adapter.php line 380 at AwsS3Adapter->writeStream(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in Filesystem.php line 122 at Filesystem->putStream(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, object(Config))in FilesystemAdapter.php line 194 at FilesystemAdapter->put(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource, array())in Disk.php line 61 at Disk->put(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, resource)in Disk.php line 82 at Disk->copy(object(LocalTemporaryFile), ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’)in Excel.php line 102 at Excel->store(object(Unsubscribes), ‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, ‘s3’, ‘Csv’, array())in Exportable.php line 52 at Unsubscribes->store(‘exports/local/Greyght-unsubscribes-2014-07-10-to-2019-04-11.csv’, ‘s3’, ‘Csv’)in Export.php line 72 at Export->exportUnsubscribes()in DashboardController.php line 270 at DashboardController->exportUnsubscribes() at call_user_func_array(array(object(DashboardController), ‘exportUnsubscribes’), array())in Controller.php line 54 at Controller->callAction(‘exportUnsubscribes’, array())in ControllerDispatcher.php line 45 at ControllerDispatcher->dispatch(object(Route), object(DashboardController), ‘exportUnsubscribes’)in Route.php line 219 at Route->runController()in Route.php line 176 at Route->run()in Router.php line 680 at Router->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 30 at Pipeline->Illuminate\Routing{closure}(object(Request))in MainController.php line 49 at MainController->App\Http\Controllers\App{closure}(object(Request), object(Closure))in Pipeline.php line 145 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in VerifyCsrfToken.php line 22 at VerifyCsrfToken->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AppAuthentication.php line 61 at AppAuthentication->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in TrustProxies.php line 57 at TrustProxies->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AccountHostnameMiddleware.php line 21 at AccountHostnameMiddleware->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in CreateFreshApiToken.php line 50 at CreateFreshApiToken->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in SubstituteBindings.php line 41 at SubstituteBindings->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AuthenticateSession.php line 58 at AuthenticateSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in ShareErrorsFromSession.php line 49 at ShareErrorsFromSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in StartSession.php line 56 at StartSession->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in AddQueuedCookiesToResponse.php line 37 at AddQueuedCookiesToResponse->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in EncryptCookies.php line 66 at EncryptCookies->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 104 at Pipeline->then(object(Closure))in Router.php line 682 at Router->runRouteWithinStack(object(Route), object(Request))in Router.php line 657 at Router->runRoute(object(Request), object(Route))in Router.php line 623 at Router->dispatchToRoute(object(Request))in Router.php line 612 at Router->dispatch(object(Request))in Kernel.php line 176 at Kernel->Illuminate\Foundation\Http{closure}(object(Request))in Pipeline.php line 30 at Pipeline->Illuminate\Routing{closure}(object(Request))in ServeNova.php line 26 at ServeNova->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in InjectDebugbar.php line 58 at InjectDebugbar->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in CheckForMaintenanceMode.php line 62 at CheckForMaintenanceMode->handle(object(Request), object(Closure))in Pipeline.php line 163 at Pipeline->Illuminate\Pipeline{closure}(object(Request))in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request))in Pipeline.php line 104 at Pipeline->then(object(Closure))in Kernel.php line 151 at Kernel->sendRequestThroughRouter(object(Request))in Kernel.php line 116 at Kernel->handle(object(Request))in index.php line 52

Additional Information

I have 2 instances of our application so I tested this on the 5.7 version to see if there was something configured wrong on my local environment but the same export worked as expected so it appears to be an issue with the upgrade. The previous version of laravel excel was 3.1.6 (I don’t believe I missed anything with upgrading to 3.1.11).

I tried changing the excel config file for exports.csv to use “\r\n” for the line ending setting but that didn’t change the behavior any.

Then I tried viewing the contents of the file by doing a dd right before the exception is thrown in SignatureV4 and I was able to read the contents fine (from the dump statement) so it seems it’s related to the Psr7\hash function. The 1/2 exception shows “Cannot read from non-readable stream” and when I dumped the data for $request->getBody() it shows readable as false. I’m not sure how/why this happens but it seems to be related to the overall issue. Stream {#25561 ▼ -stream: stream resource @59 ▼ timed_out: false blocked: true eof: false wrapper_type: “plainfile” stream_type: “STDIO” mode: “rb+” unread_bytes: 0 seekable: true uri: “/tmp/tmp-laravel-excel/laravel-excel-J374kbEboqVHytyJLIH4MaxiIgp66cri” options: [] } -size: 172 -seekable: true -readable: false -writable: false -uri: “/tmp/tmp-laravel-excel/laravel-excel-J374kbEboqVHytyJLIH4MaxiIgp66cri” -customMetadata: [] } I am using a custom tmp directory as well

The aws sdk hasn’t changed during this upgrade (version 3.64.5 if it helps). I then tried putting a file into s3 with the traditional laravel function and it worked fine so I don’t think it’s an s3 config issue.

\Illuminate\Support\Facades\Storage::disk('s3')->put('exports/local/test.csv','test,another');

The export class implements FromQuery, WithHeadings, WithMapping The class is called by doing:

(new Unsubscribes($this->start_date, $this->end_date))->forAccount($this->account)->store($path, 's3', \Maatwebsite\Excel\Excel::CSV); 

I also tried setting the “visibility” option but still got the error. I tried creating the file using the storage facade thinking it was some weird permission/access thing but the same error occurred.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 17 (6 by maintainers)

Most upvoted comments

/** @var array Hash of readable and writable stream types */ private static $readWriteHash = [ 'read' => [ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a+' => true ], 'write' => [ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true ] ];

the problem here is with older versions of guzzlehttp/psr7. In vendor/guzzlehttp/psr7/src/Stream.php where it considers any stream with a mode not belonging to $readWriteHash[‘read’] as non-readable, and that’s what happening with the ‘rb+’ mode. Since ‘r+b’ belongs to the above array it doesn’t throw that checksum exception