peanut's avatar

Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed

I'm not sure what this error is for since I have been using this throughout my entire site and it works fine in those areas. This is my model:

<?php namespace Duplicolor\Models\User;

use \Illuminate\Auth\UserTrait;
use \Illuminate\Auth\UserInterface;
use \Illuminate\Auth\Reminders\RemindableTrait;
use \Illuminate\Auth\Reminders\RemindableInterface;
use \Input;
use \Auth;
use \Config;
use \Intellectproductions\Verify\Verify;
use \Zizaco\Entrust\HasRole;
use \Laracasts\Presenter\PresentableTrait;
use \Duplicolor\Traits\ApprovalTrait;
use \Duplicolor\Traits\BaseTrait;
use \Duplicolor\Helpers\Uploader;
use \Session;

class User extends Verify implements UserInterface, RemindableInterface {

    use UserTrait, RemindableTrait, HasRole, PresentableTrait, ApprovalTrait, BaseTrait;

    public static $rules = array(
        'username'              => 'sometimes|required|max:50|unique:users,username',
        'email'                 => 'sometimes|required|email|max:50|unique:users,email',
        'password'              => 'sometimes|required|confirmed',
        'password_confirmation' => 'sometimes|required',
        'first_name'            => 'sometimes|required|max:45',
        'last_name'             => 'sometimes|required|max:45',
        'street'                => 'max:100',
        'city'                  => 'sometimes|required|max:45',
        'state'                 => 'max:2',
        'zip'                   => 'max:7',
        'country'               => 'max:50',
        'rules'                 => 'sometimes|required|accepted',
        'show_name'             => 'boolean',
        'avatar'                => 'image',
        'banner'                => 'image'
    );

    protected $fillable = array('first_name', 'last_name', 'street', 'city', 'state', 'zip', 'country', 'rules', 'signup', 'show_name');

    protected $presenter = '\Duplicolor\Presenters\User\UserPresenter';

    protected $identify = array('email', 'username'); // identify column in the db
    protected static $directory; // User avatar directory
    protected static $bannerDirectory; // User banner directory

    protected static $avatarWidth = 124;
    protected static $avatarHeight = 124;

    protected static $bannerWidth = 1024;
    protected static $bannerHeight = 338;

    function __construct($attributes = array()) {
        parent::__construct($attributes);

        $this->purgeFilters[] = function($key) {
            $purge = array('rules', 'signup');
            return ! in_array($key, $purge);
        };

        $this->approvalColumn = 'confirmed';
        self::$directory = Config::get('app.url') . Config::get('app.userPath');
        self::$bannerDirectory = Config::get('app.url') . Config::get('app.userBannerPath');
    }

    public static function boot()
    {
        parent::boot();

        User::saving(function($user)
        {
            // Check to see if they are changing their avatar
            if( ! is_null(Session::get('avatar')) )
            {
                // Upload image and get filename
                $uploader = new Uploader();
                $uploader->setDirectory(static::$directory);
                if( ! $uploader->uploadImage( Session::get('avatar'), array(static::$avatarWidth, static::$avatarHeight) ) )
                {
                    return false;
                }

                $this->avatar = $uploader->getRecentFile();
            }

            // Check to see if they are changing their banner
            if( ! is_null(Session::get('banner')) )
            {
                // Upload image and get filename
                $uploader = new Uploader();
                $uploader->setDirectory(static::$bannerDirectory);
                if( ! $uploader->uploadImage( Session::get('banner'), array(static::$bannerWidth, static::$bannerHeight) ) )
                {
                    return false;
                }

                $this->banner = $uploader->getRecentFile();
            }
        });
    }
}

My Uploader class looks like this:

<?php namespace Duplicolor\Helpers;

/**
 * Uploader Class
 * 
 * All methods related to handling files and using the Resizer object
 *
 * @author Haley Schillig <http://intellectproductions.com/>
 * @version 1.0
 * 
 */

use \Auth;
use \File;
use \Imager;

class Uploader {

    protected $directory; // Directory for images
    protected $recentFileUpload; // Recent file upload
    protected $width; // Width of image if resized
    protected $height; // Height of image if resized

    public function setDirectory( $value )
    {
        $this->directory = $value;
    }

    public function getRecentFile()
    {
        return $this->recentFileUpload;
    }

    /**
     * Upload images
     * @param image         Image object
     * @param resizeArgs    Width and height of image
     *
     */
    public function uploadImage( $image, array $resizeArgs = array() )
    {
          $fileName = $this->generateFileName( $image );

        $image->move($this->directory, $fileName);

            // now resize and upload
            if(count($resizeArgs) > 0)
            {
                // Set width and height
                $this->width = $resizeArgs[0];
                $this->height = $resizeArgs[1];

                // Resize image
                $this->resize($this->directory . $fileName);
            }

            $this->recentFileUpload = $fileName;

            return true;
    }
}

I didn't show the entire class because the error is specifically being thrown at this line:

$image->move($this->directory, $fileName);

I did a dd on the $image and it is returning the image object when the form is set to files => true so that's coming back fine. $this->directory holds the correct directory and $fileName holds the right value that was expected.

This is how I'm executing it all:

/**
 * Edit banner of user
 *
 */
public function postEditBanner()
{
    $user = $this->user->getById( Auth::id() );
    Session::put('banner', Input::file('graphic'));

    if( ! $user->updateUniques() )
    {
        return Redirect::to(URL::previous())
            ->withInput(Input::except('graphic'))
            ->withErrors( $user->errors()->all() );
    }

    return Redirect::to(URL::previous())
        ->withInput(Input::except('graphic'))
        ->with('success', 'Your banner was changed successfully');
}

Thanks if anyone can see anything blaringly wrong..

0 likes
10 replies
thepsion5's avatar

This is just a guess, but it may be that a temporary file can't be serialized because it expires at the end of the request. I would ASSUME that the error would be thrown when you try to store it in the session, but it look like it may be happening when you try to use it instead. Instead of storing the file right in the session, using the UploadedFile class, see if you can do something like copy it to the temp directory and then save a new File class to the session instead.

peanut's avatar

Wait so I call the ->move() in the controller or model or whatever and then do the rest from the session? Like I write the result in the session after calling that?'

EDIT Ok I tried just doing Input::file('graphic') directly and it still says that same error message which doesn't make sense because it works other places where I use Input::file()

peanut's avatar

Hmm I got pretty far on it.. it goes down to the very end of the boot which I added a return true just in case.. but it's with my Redirect it seems.. Because it goes back down to the success part...

My form looks like this:

<div id="graphic-modal" class="modal fade">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4>Upload Graphic</h4>
            </div>
            {{ Form::open(array('url' => '/', 'method' => 'post', 'id' => 'changeGraphicForm', 'files' => true)) }}
             <div class="modal-body">
     <div class="row">
      <div class="col-12">
       <label>Choose File:</label>
       {{ Form::file('graphic') }}
      </div>
     </div>
             </div>
             <div class="modal-footer">
                 <button type="submit" class="btn-green">Upload <i class="fa fa-upload icon-right"></i></button>
             </div>
            {{ Form::close() }}
        </div>
    </div>
</div>

Is there something wrong with that?

EDIT I didn't know if it was something with remembering input so I tried this:

<div id="graphic-modal" class="modal fade">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4>Upload Graphic</h4>
            </div>
            <form action="/" accept-charset="UTF-8" id="changeGraphicForm" enctype="multipart/form-data" method="post">
            {{ Form::token() }}
             <div class="modal-body">
     <div class="row">
      <div class="col-12">
       <label>Choose File:</label>
       <input type="file" name="graphic" />
      </div>
     </div>
             </div>
             <div class="modal-footer">
                 <button type="submit" class="btn-green">Upload <i class="fa fa-upload icon-right"></i></button>
             </div>
            </form>
        </div>
    </div>
</div>

And it still returns that error message.. everything executes fine. Database updates, the image uploads, etc... it returns as a success, but for some odd reason, it's just throwing this with the Redirect.

thepsion5's avatar

Does it work if you take out the 'withInput' line of your successful redirect? And can you paste a link to the whole stack trace? That might help.

peanut's avatar

I tried this controller method as well (I also tried it without the Session and accessed Input::get('graphic') directly in the saving method):

/**
 * Edit banner of user
 *
 */
public function postEditBanner()
{
    $user = $this->user->getById( Auth::id() );
    Session::put('banner', Input::file('graphic'));

    if( ! $user->updateUniques() )
    {
        return Redirect::to(URL::previous())
            ->withErrors( $user->errors()->all() );
    }

    return Redirect::to('garage')
        ->with('success', 'Your banner was changed successfully');
}

Here is the complete stack trace:

8. Exception
…\vendor\laravel\framework\src\Illuminate\Session\Store.php220
7. serialize
…\vendor\laravel\framework\src\Illuminate\Session\Store.php220
6. Illuminate\Session\Store save
…\vendor\laravel\framework\src\Illuminate\Session\Middleware.php126
5. Illuminate\Session\Middleware closeSession
…\vendor\laravel\framework\src\Illuminate\Session\Middleware.php79
4. Illuminate\Session\Middleware handle
…\vendor\laravel\framework\src\Illuminate\Cookie\Queue.php47
3. Illuminate\Cookie\Queue handle
…\vendor\laravel\framework\src\Illuminate\Cookie\Guard.php51
2. Illuminate\Cookie\Guard handle
…\vendor\stack\builder\src\Stack\StackedHttpKernel.php23
1. Stack\StackedHttpKernel handle
…\vendor\laravel\framework\src\Illuminate\Foundation\Application.php642
0. Illuminate\Foundation\Application run
…\public\index.php49

This is the exact error message:

Exception 
Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed

It's called in Session/Store.php. The URL is still garage/settings/edit-banner when it throws the error message, not the redirected URL which is garage/project

1 like
JeffreyWay's avatar

Quickly scanned this thread, but it's probably because the file data is being included with the returned input, and it can't be serialized. Try excluding that.

1 like
jonathanmartins's avatar

Hey Jeffrey,

How can I solve this problem working on Laravel 5 using FromRequest class? It seems to do the validation correctly, but if the validation fails Laravel attempt to redirect back automatically, and in my case this is the moment that the problem occurs.

jonathanmartins's avatar

I got it! Like everything in Laravel, it very simple!

I just put...

$dontFlash = [ 'file' ];

...on my custom FromRequest class!

3 likes
reinvanleirsberghe's avatar

jonathanmartins can you show me the code of the FromRequest class? I can't figure out where you put

$dontFlash = [ 'file' ];

Thanks!

bashy's avatar

Was a month ago now but I guess you add it to the top of the class

Please or to participate in this conversation.