From 38053ceb4a75306c671f6d7dc61528889966e260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 12:32:42 +0200 Subject: [PATCH 1/6] Add ng-file-upload handler --- .../ChunksInRequestNgFileUploadHandler.php | 71 +++++++++++++++++++ src/Handler/HandlerFactory.php | 3 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/Handler/ChunksInRequestNgFileUploadHandler.php diff --git a/src/Handler/ChunksInRequestNgFileUploadHandler.php b/src/Handler/ChunksInRequestNgFileUploadHandler.php new file mode 100644 index 0000000..2fc5e89 --- /dev/null +++ b/src/Handler/ChunksInRequestNgFileUploadHandler.php @@ -0,0 +1,71 @@ +has(static::KEY_CHUNK_NUMBER) && $request->has(static::KEY_TOTAL_SIZE) + && $request->has(static::KEY_CHUNK_SIZE) + && $request->has(static::KEY_CHUNK_CURRENT_SIZE); + } + + /** + * Returns current chunk from the request + * + * @param Request $request + * + * @return int + */ + protected function getTotalChunksFromRequest(Request $request) { + return intval( + ceil($request->get(static::KEY_TOTAL_SIZE) / $request->get(static::KEY_CHUNK_SIZE)) + ); + } +} diff --git a/src/Handler/HandlerFactory.php b/src/Handler/HandlerFactory.php index 6fce6e3..5bd370d 100644 --- a/src/Handler/HandlerFactory.php +++ b/src/Handler/HandlerFactory.php @@ -14,7 +14,8 @@ class HandlerFactory ChunksInRequestUploadHandler::class, ResumableJSUploadHandler::class, DropZoneUploadHandler::class, - ChunksInRequestSimpleUploadHandler::class + ChunksInRequestSimpleUploadHandler::class, + ChunksInRequestNgFileUploadHandler::class, ); /** From 8769d4cd44491599b6ca872bf40066df8637fa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 12:35:17 +0200 Subject: [PATCH 2/6] Update readme for the support of ng-file-upload --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index e06f78c..6271a1f 100644 --- a/readme.md +++ b/readme.md @@ -47,6 +47,7 @@ Setup is composed in 3 steps: | [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload) | [Wiki](https://github.com/pionl/laravel-chunk-upload/wiki/blueimp-file-upload) | :heavy_check_mark: | :heavy_multiplication_x: | | [Plupload](https://github.com/moxiecode/plupload) | [Wiki](https://github.com/pionl/laravel-chunk-upload/wiki/plupload) | :heavy_check_mark: | :heavy_multiplication_x: | | [simple uploader](https://github.com/simple-uploader) | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_multiplication_x: | +| [ng-file-upload](https://github.com/danialfarid/ng-file-upload) | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_multiplication_x: | For more detailed information (tips) use the [Wiki](https://github.com/pionl/laravel-chunk-upload/wiki) or for working example continue to separate repository with [example](https://github.com/pionl/laravel-chunk-upload-example). From e130729e6fd51cd19d4ba2ee00391dc0d000d6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 16:12:46 +0200 Subject: [PATCH 3/6] Refactor ChunksInRequestNgFileUploadHandler class to NgFileUploadHandler --- src/Handler/HandlerFactory.php | 2 +- ...estNgFileUploadHandler.php => NgFileUploadHandler.php} | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) rename src/Handler/{ChunksInRequestNgFileUploadHandler.php => NgFileUploadHandler.php} (87%) diff --git a/src/Handler/HandlerFactory.php b/src/Handler/HandlerFactory.php index 5bd370d..7904cdd 100644 --- a/src/Handler/HandlerFactory.php +++ b/src/Handler/HandlerFactory.php @@ -15,7 +15,7 @@ class HandlerFactory ResumableJSUploadHandler::class, DropZoneUploadHandler::class, ChunksInRequestSimpleUploadHandler::class, - ChunksInRequestNgFileUploadHandler::class, + NgFileUploadHandler::class, ); /** diff --git a/src/Handler/ChunksInRequestNgFileUploadHandler.php b/src/Handler/NgFileUploadHandler.php similarity index 87% rename from src/Handler/ChunksInRequestNgFileUploadHandler.php rename to src/Handler/NgFileUploadHandler.php index 2fc5e89..7c36fda 100644 --- a/src/Handler/ChunksInRequestNgFileUploadHandler.php +++ b/src/Handler/NgFileUploadHandler.php @@ -5,7 +5,7 @@ use Illuminate\Http\Request; /** - * Class ChunksInRequestNgFileUploadHandler + * Class NgFileUploadHandler * * Upload receiver that detects the content range from he request value - chunks * Works with: @@ -13,7 +13,8 @@ * * @package Pion\Laravel\ChunkUpload\Handler */ -class ChunksInRequestNgFileUploadHandler extends ChunksInRequestUploadHandler { +class NgFileUploadHandler extends ChunksInRequestUploadHandler +{ /** * Key for number of sending chunk @@ -51,7 +52,8 @@ class ChunksInRequestNgFileUploadHandler extends ChunksInRequestUploadHandler { * @return bool */ public static function canBeUsedForRequest(Request $request) { - return $request->has(static::KEY_CHUNK_NUMBER) && $request->has(static::KEY_TOTAL_SIZE) + return $request->has(static::KEY_CHUNK_NUMBER) + && $request->has(static::KEY_TOTAL_SIZE) && $request->has(static::KEY_CHUNK_SIZE) && $request->has(static::KEY_CHUNK_CURRENT_SIZE); } From 965965b1a74c8aec47f4e17f5642900063d34add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 16:20:50 +0200 Subject: [PATCH 4/6] phpcs reformat --- src/Handler/ChunksInRequestSimpleUploadHandler.php | 1 - src/Handler/NgFileUploadHandler.php | 6 ++++-- src/Handler/SingleUploadHandler.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Handler/ChunksInRequestSimpleUploadHandler.php b/src/Handler/ChunksInRequestSimpleUploadHandler.php index d105933..6f26cca 100644 --- a/src/Handler/ChunksInRequestSimpleUploadHandler.php +++ b/src/Handler/ChunksInRequestSimpleUploadHandler.php @@ -1,7 +1,6 @@ has(static::KEY_CHUNK_NUMBER) && $request->has(static::KEY_TOTAL_SIZE) && $request->has(static::KEY_CHUNK_SIZE) @@ -65,7 +66,8 @@ public static function canBeUsedForRequest(Request $request) { * * @return int */ - protected function getTotalChunksFromRequest(Request $request) { + protected function getTotalChunksFromRequest(Request $request) + { return intval( ceil($request->get(static::KEY_TOTAL_SIZE) / $request->get(static::KEY_CHUNK_SIZE)) ); diff --git a/src/Handler/SingleUploadHandler.php b/src/Handler/SingleUploadHandler.php index 617ab6e..f888760 100644 --- a/src/Handler/SingleUploadHandler.php +++ b/src/Handler/SingleUploadHandler.php @@ -25,7 +25,7 @@ class SingleUploadHandler extends AbstractHandler */ public function startSaving($chunkStorage) { - return new SingleSave($this->file, $this, $this->config); + return new SingleSave($this->file, $this, $this->config); } /** From fb1525153a8c241c8c015d50858ddee94fccfd04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 17:19:48 +0200 Subject: [PATCH 5/6] Add unit test for NgFileUpload handler --- phpunit.xml | 3 +- src/Exceptions/ChunkInvalidValueException.php | 28 +++ src/Handler/NgFileUploadHandler.php | 66 +++++- tests/Handler/NgFileUploadHandlerTest.php | 197 ++++++++++++++++++ 4 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 src/Exceptions/ChunkInvalidValueException.php create mode 100644 tests/Handler/NgFileUploadHandlerTest.php diff --git a/phpunit.xml b/phpunit.xml index 35c51dd..baf9b7f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,7 +7,8 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - syntaxCheck="false"> + syntaxCheck="false" + bootstrap="vendor/autoload.php"> ./tests/ diff --git a/src/Exceptions/ChunkInvalidValueException.php b/src/Exceptions/ChunkInvalidValueException.php new file mode 100644 index 0000000..b62bb50 --- /dev/null +++ b/src/Exceptions/ChunkInvalidValueException.php @@ -0,0 +1,28 @@ +has(static::KEY_CHUNK_NUMBER) - && $request->has(static::KEY_TOTAL_SIZE) - && $request->has(static::KEY_CHUNK_SIZE) - && $request->has(static::KEY_CHUNK_CURRENT_SIZE); + $hasChunkParams = $request->has(static::KEY_CHUNK_NUMBER) + && $request->has(static::KEY_TOTAL_SIZE) + && $request->has(static::KEY_CHUNK_SIZE) + && $request->has(static::KEY_CHUNK_CURRENT_SIZE); + + return $hasChunkParams && self::checkChunkParams($request); + } + + /** + * @return int + */ + public function getPercentageDone() + { + // Check that we have received total chunks + if (!$this->chunksTotal) { + return 0; + } + + return intval(parent::getPercentageDone()); + } + + /** + * @param Request $request + * + * @return bool + * @throws ChunkInvalidValueException + */ + protected static function checkChunkParams($request) + { + $isInteger = is_int($request->get(static::KEY_CHUNK_NUMBER)) + && is_int($request->get(static::KEY_TOTAL_SIZE)) + && is_int($request->get(static::KEY_CHUNK_SIZE)) + && is_int($request->get(static::KEY_CHUNK_CURRENT_SIZE)); + + if ($request->get(static::KEY_CHUNK_SIZE) < $request->get(static::KEY_CHUNK_CURRENT_SIZE)) { + throw new ChunkInvalidValueException(); + } + + if ($request->get(static::KEY_CHUNK_NUMBER) < 0) { + throw new ChunkInvalidValueException(); + } + + if ($request->get(static::KEY_TOTAL_SIZE) < 0) { + throw new ChunkInvalidValueException(); + } + + return $isInteger; } /** @@ -68,6 +120,10 @@ public static function canBeUsedForRequest(Request $request) */ protected function getTotalChunksFromRequest(Request $request) { + if (!$request->get(static::KEY_CHUNK_SIZE)) { + return 0; + } + return intval( ceil($request->get(static::KEY_TOTAL_SIZE) / $request->get(static::KEY_CHUNK_SIZE)) ); diff --git a/tests/Handler/NgFileUploadHandlerTest.php b/tests/Handler/NgFileUploadHandlerTest.php new file mode 100644 index 0000000..dcf7f88 --- /dev/null +++ b/tests/Handler/NgFileUploadHandlerTest.php @@ -0,0 +1,197 @@ +assertFalse($ngFileUpload->isChunkedUpload()); + } + + /** + * @throws \Exception + */ + public function testInitWithChunk() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 10, + '_totalSize' => 5000, + '_chunkSize' => 500, + '_currentChunkSize' => 500, + ] + ); + $file = UploadedFile::fake(); + + /** @var UploadedFile $file */ + $ngFileUpload = new NgFileUploadHandler($request, $file, new FileConfig()); + + $this->assertTrue($ngFileUpload->isChunkedUpload()); + } + + /** + * @throws \Exception + */ + public function testPercentageDoneWithoutChunk() + { + $request = Request::create('test', 'POST', [], [], [], []); + $file = UploadedFile::fake(); + + /** @var UploadedFile $file */ + $ngFileUpload = new NgFileUploadHandler($request, $file, new FileConfig()); + + $this->assertEquals(0, $ngFileUpload->getPercentageDone()); + } + + /** + * @throws \Exception + */ + public function testValidNgFileUploadFirstChunk() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 0, + '_totalSize' => 5000, + '_chunkSize' => 500, + '_currentChunkSize' => 500, + ] + ); + $file = UploadedFile::fake()->create('test'); + + $ngFileUpload = new NgFileUploadHandler($request, $file, new FileConfig()); + + $this->assertEquals(1, $ngFileUpload->getCurrentChunk()); + $this->assertEquals(10, $ngFileUpload->getTotalChunks()); + $this->assertEquals(10, $ngFileUpload->getPercentageDone()); + $this->assertTrue($ngFileUpload->isChunkedUpload()); + $this->assertFalse($ngFileUpload->isLastChunk()); + $this->assertTrue($ngFileUpload->isFirstChunk()); + } + + /** + * @throws \Exception + */ + public function testValidNgFileUploadNextChunk() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 1, + '_totalSize' => 5000, + '_chunkSize' => 500, + '_currentChunkSize' => 500, + ] + ); + $file = UploadedFile::fake(); + + /** @var UploadedFile $file */ + $ngFileUpload = new NgFileUploadHandler($request, $file, new FileConfig()); + + $this->assertEquals(2, $ngFileUpload->getCurrentChunk()); + $this->assertEquals(10, $ngFileUpload->getTotalChunks()); + $this->assertEquals(20, $ngFileUpload->getPercentageDone()); + $this->assertTrue($ngFileUpload->isChunkedUpload()); + $this->assertFalse($ngFileUpload->isLastChunk()); + $this->assertFalse($ngFileUpload->isFirstChunk()); + } + + /** + * @throws \Exception + */ + public function testIsLastChunk() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 9, + '_totalSize' => 5000, + '_chunkSize' => 500, + '_currentChunkSize' => 500, + ] + ); + $file = UploadedFile::fake(); + + /** @var UploadedFile $file */ + $ngFileUpload = new NgFileUploadHandler($request, $file, new FileConfig()); + + $this->assertEquals(10, $ngFileUpload->getCurrentChunk()); + $this->assertEquals(10, $ngFileUpload->getTotalChunks()); + $this->assertEquals(100, $ngFileUpload->getPercentageDone()); + $this->assertTrue($ngFileUpload->isLastChunk()); + $this->assertFalse($ngFileUpload->isFirstChunk()); + } + + /** + * Checks if canBeUsedForRequest returns false when chunk is missing + * + * @throws \Exception + */ + public function testCanBeUsedForInvalidRequest() + { + $request = Request::create('test', 'POST', [], [], [], []); + $this->assertFalse(NgFileUploadHandler::canBeUsedForRequest($request)); + } + + /** + * Checks if canBeUsedForRequest returns false when content-range is invalid + * + * @throws \Exception + */ + public function testCanBeUsedForInvalidContentRangeFormat() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 'xx', + '_totalSize' => 'xx', + '_chunkSize' => 'xx', + '_currentChunkSize' => 'xx', + ] + ); + $this->assertFalse(NgFileUploadHandler::canBeUsedForRequest($request)); + } + + /** + * Checks if canBeUsedForRequest returns false when content-range is missing + * + * @throws \Exception + */ + public function testCanBeUsedForValidRange() + { + $request = Request::create( + 'test', + 'POST', + [ + '_chunkNumber' => 0, + '_totalSize' => 10, + '_chunkSize' => 10, + '_currentChunkSize' => 10, + ] + ); + $this->assertTrue(NgFileUploadHandler::canBeUsedForRequest($request)); + } +} From 4def7979f66516f45b8bf8a6d1c49762a527d70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=CC=81opold=20Jacquot?= Date: Wed, 30 May 2018 17:41:13 +0200 Subject: [PATCH 6/6] Fix ngfileupload integer params verification --- src/Handler/NgFileUploadHandler.php | 8 ++++---- tests/Handler/NgFileUploadHandlerTest.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Handler/NgFileUploadHandler.php b/src/Handler/NgFileUploadHandler.php index ada3900..a2c274d 100644 --- a/src/Handler/NgFileUploadHandler.php +++ b/src/Handler/NgFileUploadHandler.php @@ -91,10 +91,10 @@ public function getPercentageDone() */ protected static function checkChunkParams($request) { - $isInteger = is_int($request->get(static::KEY_CHUNK_NUMBER)) - && is_int($request->get(static::KEY_TOTAL_SIZE)) - && is_int($request->get(static::KEY_CHUNK_SIZE)) - && is_int($request->get(static::KEY_CHUNK_CURRENT_SIZE)); + $isInteger = ctype_digit($request->input(static::KEY_CHUNK_NUMBER)) + && ctype_digit($request->input(static::KEY_TOTAL_SIZE)) + && ctype_digit($request->input(static::KEY_CHUNK_SIZE)) + && ctype_digit($request->input(static::KEY_CHUNK_CURRENT_SIZE)); if ($request->get(static::KEY_CHUNK_SIZE) < $request->get(static::KEY_CHUNK_CURRENT_SIZE)) { throw new ChunkInvalidValueException(); diff --git a/tests/Handler/NgFileUploadHandlerTest.php b/tests/Handler/NgFileUploadHandlerTest.php index dcf7f88..57f647d 100644 --- a/tests/Handler/NgFileUploadHandlerTest.php +++ b/tests/Handler/NgFileUploadHandlerTest.php @@ -186,10 +186,10 @@ public function testCanBeUsedForValidRange() 'test', 'POST', [ - '_chunkNumber' => 0, - '_totalSize' => 10, - '_chunkSize' => 10, - '_currentChunkSize' => 10, + '_chunkNumber' => '0', + '_totalSize' => '10', + '_chunkSize' => '10', + '_currentChunkSize' => '10', ] ); $this->assertTrue(NgFileUploadHandler::canBeUsedForRequest($request));