Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

hightechredneckwoman's avatar

Session flash data disappears with file upload

I have run into a weird issue with session flash data when submitting a form with a file upload. The session flash data disappears only if a file is being uploaded. If no file is uploaded, then the session flash data is there as it should be.

I have a view with a form that includes file upload fields. In the update() method in my controller, I'm using a custom Request to handle the validation for the regular form fields. In the method itself, I'm doing some additional validation on the file being uploaded (i.e. required, allowed file type, under max file size, name required). The file upload is optional. Multiple files can be uploaded.

If I run into a validation issue with the file upload, I'm redirecting to the edit() method and including an error message and an array with info about the file(s) uploaded.

return Redirect::route('my-named-route', ['id' => $id])->withInput()->with('data', $data)->withError('Error encountered');

If I include a file upload field but don't set a name or upload a file, I get a validation error displayed in my view (as I should). However, if I select a file to upload but leave the name blank, no validation error is displayed even though it should be.

I have verified that the proper validation error is set in the update() method in my controller (either no file uploaded or file of wrong type) and included in the redirect, however once I get redirected to the edit() method, all of my session flash data is gone, including the form input data.

This only happens if I select a file for the file upload field. If I do not, then everything works as it should. Exact same code in both instances. Only the data in the $request object is different.

I have verified that the token for the session is the same in all instances. I also set a normal (non-flash) session variable that is carried through all of my testing. I even deleted my session and started testing fresh to make sure I didn't have an issue with that session, but my problems did not go away.

I'm using Laravel 5.1, so I know it isn't an issue with web middleware (since that was added in 5.2).

Any ideas as to what might be going on?

0 likes
3 replies
hightechredneckwoman's avatar

This is my edit() method. NOTE: I've stripped out some code that isn't relevant to my issue. It is just setting up my theme.

public function edit($id)
{
    $voice = Voice::with('demos')->find($id);
    if(empty($voice))
    {
        return Redirect::route('admin::voices.index')->withError('The voice talent you are trying to modify does not exist.');
    }
    
    // display the page
    return $this->theme->of('admin.voices.edit', compact('voice'))->render();
}

This is my update() method. As with the edit() method, I've removed some code that isn't relevant to my issue.

public function update(SaveVoiceRequest $request, FlysystemManager $flysystem, $id)
{
    $voice = Voice::find($id);
    if(empty($voice))
    {
        return Redirect::route('admin::voices.index')->withError('The voice talent you are trying to modify does not exist.');
    }

    // are demos being uploaded?
    if($request->has('demo_names'))
    {
        $errors             = [];
        $demos              = [];
        $max_filesize       = Config::get('voices.max_filesize');
        $allowed_filetypes  = Config::get('voices.allowed_filetypes');

        foreach($form_values['demo_names'] as $key => $name)
        {
            $count      = $key+1;
            $file       = $form_values['demo_files'][$key];
            $filename   = (!empty($file)) ? $file->getClientOriginalName() : null;
            $extension  = (!empty($file)) ? $file->getClientOriginalExtension() : null;
            $size       = (!empty($file)) ? $file->getClientSize() : null;

            // VALIDATION:
            // - name required
            if(empty($name))
            {
                $errors[] = '<li>You must enter a name for demo #'.$count.'.</li>';
            }

            // - file required
            if(empty($file))
            {
                $errors[] = '<li>You must upload a file for demo #'.$count.'.</li>';
            }
            // - file type allowed
            else if(!in_array($extension, $allowed_filetypes))
            {
                $errors[] = '<li>You uploaded an invalid file for demo #'.$count.'. It must be one of the following types: '.implode(', ', $allowed_filetypes).'</li>';
            }
            // - file size less than maximum size
            else if($size > $max_filesize)
            {
                $errors[] = '<li>You must upload a file smaller than the maximum allowed ('.NumberHelper::convertBytesToString($max_filesize).') for demo #'.$count.'.</li>';
            }
            // - file name unique
            else if(VoiceDemo::where('filename', $filename)->exists())
            {
                $errors[] = '<li>A file with the same name as the file you uploaded for demo #'.$count.' already exists.</li>';
            }

            $demos[] = ['name' => $name, 'filename' => $filename, 'file' => $file];
        }

        // were there any validation issues with the uploaded files?
        if(!empty($errors))
        {
            return Redirect::route('admin::voices.edit', ['id' => $id])->withInput()->with('demos', $demos)->withError('The voice talent could not be updated. Please address the following issues and try again.<ul>'.implode('', $errors).'</ul>');
        }
    }

    if($voice->update($form_values) === true)
        return Redirect::route('admin::voices.edit', ['id' => $id])->withSuccess('The voice talent has been successfully updated.');
    else
        return Redirect::route('admin::voices.edit', ['id' => $id])->withInput()->withError('An error was encountered while attempting to update the voice talent.');
}

As for my Form Request, I'm just setting up the validation rules and messages in that.

In my view, I have the following code that displays the validation error message.

@if(Session::has('error'))
    <div class="alert-box alert"><i class="fa fa-lg fa-exclamation-circle"></i> {!! Session::get('error') !!}</div>
@endif
svpernova09's avatar

Does using validator instances work: See validation within foreach ($form_values['demo_names'] as $key => $name) { You may need to tweak rules.

public function update(SaveVoiceRequest $request, FlysystemManager $flysystem, $id)
{
    $voice = Voice::find($id);
    if (empty($voice)) {
        return Redirect::route('admin::voices.index')->withError('The voice talent you are trying to modify does not exist.');
    }

    // are demos being uploaded?
    if ($request->has('demo_names')) {
        $errors = [];
        $demos = [];
        $max_filesize = Config::get('voices.max_filesize');
        $allowed_filetypes = Config::get('voices.allowed_filetypes');

        foreach ($form_values['demo_names'] as $key => $name) {
            $count = $key + 1;
            $file = $form_values['demo_files'][$key];
            $filename = (!empty($file)) ? $file->getClientOriginalName() : null;
            $extension = (!empty($file)) ? $file->getClientOriginalExtension() : null;
            $size = (!empty($file)) ? $file->getClientSize() : null;

            $validator = Validator::make($name, [
                'name' => 'required',
                'file' => 'required|mimes:'
                    . $allowed_filetypes
                    . '|between:1,'
                    . $max_filesize
                    . '|unique:voice_demos,filename',
            ]);


            // VALIDATION:
            // - name required
//            if (empty($name)) {
//                $errors[] = '<li>You must enter a name for demo #' . $count . '.</li>';
//            }
//
//            // - file required
//            if (empty($file)) {
//                $errors[] = '<li>You must upload a file for demo #' . $count . '.</li>';
//            } // - file type allowed
//            else if (!in_array($extension, $allowed_filetypes)) {
//                $errors[] = '<li>You uploaded an invalid file for demo #' . $count . '. It must be one of the following types: ' . implode(', ', $allowed_filetypes) . '</li>';
//            } // - file size less than maximum size
//            else if ($size > $max_filesize) {
//                $errors[] = '<li>You must upload a file smaller than the maximum allowed (' . NumberHelper::convertBytesToString($max_filesize) . ') for demo #' . $count . '.</li>';
//            } // - file name unique
//            else if (VoiceDemo::where('filename', $filename)->exists()) {
//                $errors[] = '<li>A file with the same name as the file you uploaded for demo #' . $count . ' already exists.</li>';
//            }

            $demos[] = ['name' => $name, 'filename' => $filename, 'file' => $file];

            if ($validator->fails()) {
                return redirect()->route('admin::voices.edit', ['id' => $id])
                    ->withErrors($validator)
                    ->withInput()
                    ->with('demos', $demos);
            }
        }

        // were there any validation issues with the uploaded files?
        if (!empty($errors)) {
            return Redirect::route('admin::voices.edit', ['id' => $id])->withInput()->with('demos', $demos)->withError('The voice talent could not be updated. Please address the following issues and try again.<ul>' . implode('', $errors) . '</ul>');
        }
    }

    if ($voice->update($form_values) === true) {

        return Redirect::route('admin::voices.edit', ['id' => $id])->withSuccess('The voice talent has been successfully updated.');
    } else {

        return Redirect::route('admin::voices.edit', ['id' => $id])->withInput()->withError('An error was encountered while attempting to update the voice talent.');
    }
}
hightechredneckwoman's avatar
Level 1

After doing some more debugging, I traced my issue down to this line ...

$demos[] = ['name' => $name, 'filename' => $filename, 'file' => $file];

When I remove the file array key and value, then I get my session flash data in my view. I don't know if including the UploadedFile object in the array was causing the session to go over the max limit or what. I'm not using that variable in my view anyway, so I can remove it without causing problems.

@svpernova09 - I'll give that validation code a try. It looks MUCH cleaner than what I was doing. My only possible issue with it is that it redirects after one error, so if there are 3 uploaded files, I lose the 2nd and 3rd if the validation fails on the first. But it gives me ideas. :)

Please or to participate in this conversation.