phplaravellaravel-5chunked

Laravel Chunk Upload skipping one chunk


I am using laravel-chuck-upload in combination with dropzone.js. Everything works fine, the chunks are uploading and when they are uploaded the final file will be saved in S3. The problem is that 1 chunk is always missing. Sometimes .8.part is missing, sometimes .7.part is missing (they remain in the chunks directory after uploading). When I upload a video that has a total size of 9.7MB the file in S3 is 8.7MB. That is 1mb missing, the same size as the missing part. All the chunks are 1MB in size.

What could be the problem and how can I fix this?

Edit: I think I have found the problem, but not the fix. When the last chunk (10th) is uploaded it thinks all the chunks are uploaded but the 8th chunk isn't finished uploading yet.


Solution

  • Extended the DropZoneUploadHandler with my own isLastChunk method. This way the file gets uploaded when it's really the latest chunk. The only problem is that dropzone.js triggers the chunksUploaded event for the last chunk call and not for the last completed chunk.

    public function isLastChunk()
    {
        $chunkFileName = preg_replace(
            "/\.[\d]+\.".ChunkStorage::CHUNK_EXTENSION.'$/', '', $this->getChunkFileName()
        );
    
        $files = ChunkStorage::storage()->files(function ($file) use ($chunkFileName) {
            return false === Str::contains($file, $chunkFileName);
        });
    
        return (count($files) + 1) == $this->getTotalChunks();
    }
    

    To fix this problem I added a chunkUploaded function to dropzone.js to get the response of every chunk upload. Now I can do everything as I did before but with file that has all the chunks.

    I added the following to dropzone.js:

    /**
     * The callback that will be invoked when a single chunk has been uploaded for a file.
     * It gets the file for which the chunks have been uploaded as the first parameter,
     * and the `done` function as second. `done()` needs to be invoked when everything
     * needed to finish the upload process is done.
     */
    chunkUploaded: function chunkUploaded(file, response, statuscode, done) {
        done();
    },
    
    xhr.onreadystatechange = function () {
        if(this.readyState == 4) {
            _this16.options.chunkUploaded(file, this.responseText, this.status, function () {
                _this16._finished(files, '', null);
            });
        }
    };