alierfani's avatar

Laravel 5.1: How to upload multiple files from three different file input fields?

I have a form in which user should at least select one file to be uploaded. I have three file input fields like this:

        <div class="form-group col-lg-4">
                {!! Form::label('file1', 'Select file 1', ['class' => 'control-label']) !!}
                {!! Form::file('files[]', ['id'=>'file1']) !!}
            </div>
            <div class="form-group col-lg-4">
                {!! Form::label('file2', 'Select file 2', ['class' => 'control-label']) !!}
                {!! Form::file('files[]', ['id'=>'file2']) !!}
            </div>
            <div class="form-group col-lg-4">
                {!! Form::label('file3', 'Select file 3', ['class' => 'control-label']) !!}
                {!! Form::file('files[]', ['id'=>'file3']) !!}
            </div>

I should validate the presence of at least one file and the mime types in a form request. Then in the store method of the related form controller, the original file names should be stored in the three corresponding database fields(namely file1, file2, file3).

How can I implement this?

0 likes
11 replies
pmall's avatar

With what part have you problem ?

alierfani's avatar

@pmall In my controller I need to check the presence of any of these files, then move them to the desired folder but I don't know how. In case one file I can do something like this:

...
$file1=$request->file('files')->getClientOriginalName();
        $request->file('files')->move(
            base_path().'/public/uploads/', $file1
        );
        $project->file1=$file1;
        $project->save();
...

But with multiple files I don't know how.

pmall's avatar
$files = [];
if ($request->files('file1')) $files[] = $request->files('file1');
if ($request->files('file2')) $files[] = $request->files('file2');
if ($request->files('file3')) $files[] = $request->files('file3');

foreach ($files as $file)
{
    // Upload the file
}

It would be clearer to extract this logic to a separate class and inject it in the controller to use it.

Then I think you have validator rules to check if at least one of those fields is filled. http://laravel.com/docs/5.1/validation#rule-required-without-all

1 like
pmall's avatar

I dont remember, just look at the docs

alierfani's avatar

@pmall Thank you for your help. I finally came up with a solution based on your help. First of all I modified the view to look like this:

        <div class="form-group col-lg-4">
                {!! Form::label('file1', 'Select file 1', ['class' => 'control-label']) !!}
                {!! Form::file('file1', ['id'=>'file1']) !!}
            </div>
            <div class="form-group col-lg-4">
                {!! Form::label('file2', 'Select file 2', ['class' => 'control-label']) !!}
                {!! Form::file('file2', ['id'=>'file2']) !!}
            </div>
            <div class="form-group col-lg-4">
                {!! Form::label('file3', 'Select file 3', ['class' => 'control-label']) !!}
                {!! Form::file('file3', ['id'=>'file3']) !!}
            </div>

Then in the controller I used your suggested code:

$files =[];
        if ($request->file('file1')) $files[] = $request->file('file1');
        if ($request->file('file2')) $files[] = $request->file('file2');
        if ($request->file('file3')) $files[] = $request->file('file3');
        foreach ($files as $file)
        {
            if(!empty($file)){
                $filename=$file->getClientOriginalName();
                $file->move(
                    base_path().'/public/uploads/', $filename
                );
            }

        }

Now I need to add some more logic to this (e.g. to prevent users from uploading duplicates). How can I separate this logic from my controller and inject it?

pmall's avatar

Just create a new class somewhere in the app folder and namespace it accordingly (ex : app/Services/UploaderService.php - App\Services\UploaderService). Then inject it in your controller action :

public function store (\App\Services\UploaderService $uploader_service, Request $request)
{
    $files =[];
        if ($request->file('file1')) $files[] = $request->file('file1');
        if ($request->file('file2')) $files[] = $request->file('file2');
        if ($request->file('file3')) $files[] = $request->file('file3');

    $uploader_service->upload($files);
}
1 like
ccarver's avatar

or

if($request->hasFile('files')){
    foreach($request->file('files') as $file) {
        $file->move(base_path().'/public/uploads/', $file->getClientOriginalName());
    }
}

This way you can reduce your input to one upload field with the multiple option. Doesn't solve your original question but just an option.

1 like
mrestufp20's avatar

@alierfani I tried the code from you but when I check in the database that appear instead of writing like this C: \ xampp \ tmp \ php15B4.tmp not .img or .doc

Please or to participate in this conversation.