Skip to content

Commit

Permalink
Large file processing in third party storage fixed 🐛
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulhaque committed Jul 30, 2024
1 parent 6695802 commit 2c93a0a
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 178 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
- name: Execute tests
run: vendor/bin/phpunit
run: vendor/bin/phpunit --exclude-group disk-test
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to `laravel-filepond` will be documented in this file.

## 11.0.2 - 2024-07-30

- Fixed large file processing in third party storage 🐛.
- Docker development environment isolated 🐳.
- Filepond disk test cases added ✅.

## 11.0.1 - 2024-07-10

- Fixed large file processing (out of memory exception) 🐛.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
A straight forward backend support for Laravel application to work with [FilePond](https://pqina.nl/filepond/) file upload javascript library. This package keeps tracks of all the uploaded files and provides an easier interface for the developers to interact with them. It currently features -

- Single and multiple file uploads.
- Chunk uploads with resume.
- Chunk uploads with resume support.
- Third party storage support.
- Global server side validation for temporary files.
- Controller/Request level validation before moving the temporary files to permanent location.
Expand Down
5 changes: 2 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
version: '3'
services:
laravel-filepond:
image: laravel-filepond-development:11.x
build:
context: ./docker/8.2
dockerfile: Dockerfile
image: laravel-filepond-development
container_name: laravel-filepond-11
container_name: laravel-filepond-11-dev
stdin_open: true
tty: true
volumes:
Expand Down
5 changes: 5 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<php>
<env name="DB_CONNECTION" value="testing"/>
<env name="APP_KEY" value="base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10="/>
<env name="AWS_ENDPOINT" value="http://minio:9000"/>
<env name="AWS_ACCESS_KEY_ID" value="key"/>
<env name="AWS_SECRET_ACCESS_KEY" value="secret"/>
<env name="AWS_DEFAULT_REGION" value="us-east-1"/>
<env name="AWS_BUCKET" value="emulated-s3"/>
</php>
<source>
<include>
Expand Down
6 changes: 5 additions & 1 deletion src/Filepond.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,11 @@ private function putFile(FilepondModel $filepond, string $path, string $disk, st

$pathInfo = pathinfo($path);

Storage::disk($permanentDisk)->putFileAs($pathInfo['dirname'], new File(Storage::disk($this->getTempDisk())->path($filepond->filepath)), $pathInfo['filename'].'.'.$filepond->extension, $visibility);
Storage::disk($permanentDisk)->writeStream(
$pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['filename'].'.'.$filepond->extension,
Storage::disk($this->getTempDisk())->readStream($filepond->filepath),
['visibility' => $visibility],
);

return [
'id' => $filepond->id,
Expand Down
170 changes: 0 additions & 170 deletions tests/Feature/FilepondFacadeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,185 +2,15 @@

namespace RahulHaque\Filepond\Tests\Feature;

use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use PHPUnit\Framework\Attributes\Test;
use RahulHaque\Filepond\Facades\Filepond;
use RahulHaque\Filepond\Tests\TestCase;
use RahulHaque\Filepond\Tests\User;

class FilepondFacadeTest extends TestCase
{
#[Test]
public function can_validate_null_filepond_file_upload()
{
Storage::disk(config('filepond.temp_disk', 'local'))->deleteDirectory(config('filepond.temp_folder', 'filepond/temp'));

$request = new Request([
'avatar' => null,
]);

try {
$request->validate([
'avatar' => Rule::filepond('required|image|mimes:jpg|size:30'),
]);
} catch (ValidationException $e) {
$this->assertEquals($e->errors(), ['avatar' => ['The avatar field is required.']]);
}
}

#[Test]
public function can_validate_after_filepond_file_upload()
{
Storage::disk(config('filepond.temp_disk', 'local'))->deleteDirectory(config('filepond.temp_folder', 'filepond/temp'));

$user = User::factory()->create();

$response = $this
->actingAs($user)
->post(route('filepond-process'), [
'avatar' => UploadedFile::fake()->image('avatar.png', 1024, 1024),
], [
'Content-Type' => 'multipart/form-data',
'accept' => 'application/json',
]);

$request = new Request([
'avatar' => $response->content(),
]);

try {
$request->validate([
'avatar' => Rule::filepond('required|image|mimes:jpg|size:30'),
]);
} catch (ValidationException $e) {
$this->assertEquals($e->errors(), [
'avatar' => [
'The avatar field must be a file of type: jpg.',
'The avatar field must be 30 kilobytes.',
],
]);
}
}

#[Test]
public function can_validate_after_multiple_filepond_file_upload()
{
Storage::disk(config('filepond.temp_disk', 'local'))->deleteDirectory(config('filepond.temp_folder', 'filepond/temp'));

$user = User::factory()->create();

$responses = [];

// Create 5 temporary file uploads
for ($i = 1; $i <= 5; $i++) {
$response = $this->actingAs($user)
->post(route('filepond-process'), [
'gallery' => UploadedFile::fake()->image('gallery-'.$i.'.png', 1024, 1024),
], [
'Content-Type' => 'multipart/form-data',
'accept' => 'application/json',
]);

$responses[] = $response->content();
}

$request = new Request([
'gallery' => $responses,
]);

try {
$request->validate([
'gallery.*' => Rule::filepond('required|image|mimes:jpg|size:30'),
]);
} catch (ValidationException $e) {
$this->assertEquals($e->errors(), [
'gallery.0' => [
'The gallery.0 field must be a file of type: jpg.',
'The gallery.0 field must be 30 kilobytes.',
],
'gallery.1' => [
'The gallery.1 field must be a file of type: jpg.',
'The gallery.1 field must be 30 kilobytes.',
],
'gallery.2' => [
'The gallery.2 field must be a file of type: jpg.',
'The gallery.2 field must be 30 kilobytes.',
],
'gallery.3' => [
'The gallery.3 field must be a file of type: jpg.',
'The gallery.3 field must be 30 kilobytes.',
],
'gallery.4' => [
'The gallery.4 field must be a file of type: jpg.',
'The gallery.4 field must be 30 kilobytes.',
],
]);
}
}

#[Test]
public function can_validate_after_nested_multiple_filepond_file_upload()
{
Storage::disk(config('filepond.temp_disk', 'local'))->deleteDirectory(config('filepond.temp_folder', 'filepond/temp'));

$user = User::factory()->create();

$responses = [];

// Create 5 temporary file uploads
for ($i = 1; $i <= 5; $i++) {
$response = $this->actingAs($user)
->post(route('filepond-process'), [
'galleries' => UploadedFile::fake()->image('gallery-'.$i.'.png', 1024, 1024),
], [
'Content-Type' => 'multipart/form-data',
'accept' => 'application/json',
]);

$responses[] = [
'title' => fake()->name(),
'image' => $response->content(),
];
}

$request = new Request([
'galleries' => $responses,
]);

try {
$request->validate([
'galleries.*.image' => Rule::filepond('required|image|mimes:jpg|size:30'),
]);
} catch (ValidationException $e) {
$this->assertEquals($e->errors(), [
'galleries.0.image' => [
'The galleries.0.image field must be a file of type: jpg.',
'The galleries.0.image field must be 30 kilobytes.',
],
'galleries.1.image' => [
'The galleries.1.image field must be a file of type: jpg.',
'The galleries.1.image field must be 30 kilobytes.',
],
'galleries.2.image' => [
'The galleries.2.image field must be a file of type: jpg.',
'The galleries.2.image field must be 30 kilobytes.',
],
'galleries.3.image' => [
'The galleries.3.image field must be a file of type: jpg.',
'The galleries.3.image field must be 30 kilobytes.',
],
'galleries.4.image' => [
'The galleries.4.image field must be a file of type: jpg.',
'The galleries.4.image field must be 30 kilobytes.',
],
]);
}
}

#[Test]
public function can_get_temporary_file_after_filepond_file_upload()
{
Expand Down
Loading

0 comments on commit 2c93a0a

Please sign in to comment.