Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
This PR introduces support for FilePond. It is fast becoming one of the more popular upload libraries, we use it heavily in a number of apps.
I have tried to build this with minimal impact on the existing core package, however there were a couple changes that I should walk through.
Only used for chunked uploads
If a file is smaller than the FilePond configured chunk size, it is uploaded simply in one single POST. FilePond does not include any special headers or parameters. Simple uploads from FilePond then get handled by the
SingleUploadHandler, and only chunked uploads end up using this new handler.Chunk data is raw request content
The
FileReceiverassumes that if you pass in a file index, it can pull the file from the Request.FilePond does not submit chunks as regular file uploads, rather it puts the data in the raw request payload. Someone has to pull that data, store it on disk somewhere, and create a fake
UploadedFileforFileReceiverto handle.This means my controller code was looking like this:
Eww. I don't like that at all. 😠
So I introduced a new factory method to
FileReceiverthat asks the handler class instead to prepare the file. This way a handler like FilePond can do what it knows needs to be done.The base
AbstractHandlerhas a new staticgetUploadedFilemethod that just mimics whatFileReceiverwhat already doing with $fileIndexOrFile`, providing full backwards compatibility. Now any handler with weird/custom file preparation steps, like FilePond, can handle it directly.Now my controller code is:
Yay. 😍
The factory method gets the handler class, has the handler prepare the file, and then instantiates the
FileReceiveras expected.I'll be eager to hear your feedback on this approach. If you don't like it, one alternative would be for me to create a custom
FilePondReceiverthat extendsFileReceiverand can handle the custom FilePond work that way. I wanted to first though try to stick with your existing core classes if possible.File index is array
If I name a FilePond instance something like
attachmentand then add multiple files, it creates hidden input form fields like this:Notice the issue? When the form is submitted, those will overwrite each other, and the server will only get one
$request->input('attachment')value.The answer is to name the FilePond instance with array syntax like
attachment[]. This works great, however it means that each uploaded file (or chunk) is array wrapped as well. You'll see that theAbstractHandler::getUploadedFilemethod that I mentioned above also checks to see if the file is an array, and unwraps it if so. The file is always the first array element.ENV in config file
One other change I made was to introduce a couple ENV variables in your config file. It seems to be a good practice for Laravel packages to allow ENV to control primary configs, without the need to publish the config file and edit directly. In my case for example, I will need to specify a different
diskdepending on my environment (local, qa, production).The fallback values are what you had before, so this is fully backwards compatible.
Full example
My working controller code is now this:
The only real differences here compared to the example repo are the 1) FileReceiver factory method, and 2) returning a unique ID (instead of throwing an exception) if no file or payload was sent.
Look forward to feedback!