Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5.1: keep uploaded file as old input

I'm using a form in Laravel 5.1 to post some text and to upload a file. It looks like this (simplified version):

{!! Form::open(array('url' => 'foo/bar')) !!}
    {!! Form::text('image_name') !!}
    {!! Form::file('image') !!}
    {!! Form::submit('Submit!') !!}
{!! Form::close() !!}

The textfield is required, so I added a $validator in my controller. If validation fails, the user is redirected back to the form. I use the withInput() method to repopulate the form so that the user doesn't have to fill it in again:

if ($validator->fails()) {
    return redirect()->back()->withInput();
}

This will get the old input back for textfields, dropdowns etc. But if the user has uploaded a file, the file selection is gone when validation fails and has to be selected again. Is there any way in Laravel to remember file selection as old input?

Thanks!

like image 857
elton73 Avatar asked Oct 15 '15 20:10

elton73


2 Answers

No, the file input can't be prepopulated by Laravel or by any software. Your website (and any website) doesn't and shouldn't know the local path to the file. Imagine the security risks if they did! You could trick a user into uploading their SSH private key or something.

What you need to do is process the uploaded file regardless, even if there are validation errors.

Then you could either store it in your database with a pending status, or have some unique hash assigned to it, with a matching hash stored in the user's session. The point is to be able to identify incomplete uploads that belong to this specific user.

Then when you display the form, retrieve those incomplete files either from the session or database, and display the thumbnail next to the file upload. This tells the user that they don't need to re-upload that file. Just make sure that they have a way to remove it as well in case they changed their mind.

Once the form is submitted correctly then clear the session hash or update the database status to complete; whatever you need to do.

like image 94
andrewtweber Avatar answered Oct 22 '22 17:10

andrewtweber


There seems to be a lot of questions around for the same issue (Form::file: How to repopulate with Input::old After Validation Errors and/or on Update?) and everyone with apparent knowledge says that is not possible.

I would proppose a workaround that covers the following goals:

  • Keep form data and file input in case of failed Laravel validation
  • Use server side validation only. You don't need SHOULD NEVER USE javascript validation.

The keyword of it all is AJAX. I would do the following:

December 2017 update: Send all fields and attached files by a single AJAX POST

  1. Create an AJAX form (method GET POST) that contains everything except including file input. Remember that it requires to send the Laravel CSRF token.
  2. In the controller validation you need to make your responses (failed or success) to make a JSON output, so your AJAX send code can get the response in any case, and then you can show it in your browser

This way you avoid to have files in any temporal state in your server.

A more complex but improved version of this process, if you are worried about used bandwidth and you expect having errors in your input fields will be very common, you may do two (or more) AJAX POST validations: The first one with the input fields only, and if it's ok, send all fields (input fields again, now including the attached files) to attempt validation again and do actions with all data in case of success.

like image 12
XaviQV Avatar answered Oct 22 '22 17:10

XaviQV