Laravel 5在多文件上传时出现TokenMismatchException错误

3
在我的Laravel 5应用程序中,管理员可以上传产品图片和产品的PDF文件。因此,表单有2个输入字段,如下所示:
<div class="col-md-4 col-sm-6">
    <div class="form-group">
        {!! Form::label('image', 'Image File:') !!}
        {!! Form::file('image', ['class' => 'form-control input-sm'] ) !!}
    </div>
</div>

<div class="col-md-4 col-sm-6">
    <div class="form-group">
        {!! Form::label('leaflet', 'Leaflet:') !!}
        {!! Form::file('leaflet', ['class' => 'form-control input-sm'] ) !!}
    </div>
</div>

当我上传的图片和传单都小于2MB时,上传成功。但是当使用大于2MB的传单时,我遇到了TokenMismatchException at line 46

在我的php.ini文件中,它位于/etc/php5/apache2/php.ini,配置如下:

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 2G

; Maximum size of POST data that PHP will accept.
; Its value may be 0 to disable the limit. It is ignored if POST data reading
; is disabled through enable_post_data_reading.
; http://php.net/post-max-size
post_max_size = 6G

我正在上传的文件(可以使用):
  1. 图片: 名称:flower-1.jpg, 大小:51.6kb
  2. PDF: 名称:productInfo.pdf, 大小:777.2kB
我正在上传的文件(无法使用——在VerifyCsrfToken.php的第46行引发了TokenMismatchException异常):
  1. 图片: 名称:flower-1.jpg, 大小:51.6kb
  2. PDF: 名称:productInfo-1.pdf, 大小:5.00MB
控制器(Controller)
public function update( $id, UpdateProductRequest $request ) {
    $product = $this->prod->findProductById($id);

    $this->prod->updateProductOfId($product->id, $request);

    Flash::success('product_general_info_updated', 'The product general information has been successfully updated.');

    return redirect()->back();
}

/**
 * Coming from ProductRespository.php
 */
public function updateProductOfId($id, Request $request)
{
    $prd = $this->findProductById($id);

    $getAllInput = $request->all();

    if($request->file('image'))
    {
        $imageType = array(
            'product' => array(
                'height' => 347,
                'width' => 347
            ),
            'category' => array(
                'height' => 190,
                'width' => 190
            )
        );

        $imageFileName =  $request->file( 'image' )->getClientOriginalName();

        foreach ( $imageType as $key => $value )
        {
            $currentFile = Input::file( 'image' );
            $fileName = $currentFile->getClientOriginalName();
            $image = Image::make( $request->file( 'image' ) );
            $name = explode( '.', $fileName );
            $destinationPath = public_path().'/images/products/uploads';
            if ( $key === 'product' ) {
                $image->resize( $value[ 'width' ], $value[ 'height' ] );
                $image->save( $destinationPath . '/' . $name[ 0 ] . "-" . $value[ 'width' ] . "-" . $value[ 'height' ] . ".jpg", 100 );
            } elseif ( $key === 'category' ) {
                $image->resize( $value[ 'width' ], $value[ 'height' ] );
                $image->save( $destinationPath . '/' . $name[ 0 ] . "-" . $value[ 'width' ] . "-" . $value[ 'height' ] . ".jpg", 100 );
            }
        }
        $getAllInput['image'] = $imageFileName;
    }

    if($request->file('leaflet'))
    {
        $currentFile = Input::file( 'leaflet' );
        $fileName = $currentFile->getClientOriginalName();
        $destinationPath = public_path().'/leaflets/products/uploads';

        $currentFile->move($destinationPath, $fileName);
        $getAllInput['leaflet'] = $fileName;
    }
    return $prd->update($getAllInput);
}

编辑1: 我正在使用表单模型绑定,因此createedit文件具有相同的表单:

<div class="container">
    @include('errors.list')

    {!! Form::open(['url' => '/admin/products', 'autocomplete' => 'off', 'files' => true]) !!}
        @include('admin.products.product_general_form', ['submitButtonText' => 'Add Product'])
    {!! Form::close() !!}
</div>
EDIT 2: 仅供参考,我正在使用Ubuntu 14.04 LTS x64位架构上的LAMP。这是本地主机。我尚未托管应用程序。
请帮助我。谢谢。

请问您能否在视图中打开表单的代码处添加您的代码? - Yoann Chambonnet
你使用Former来处理表单吗?我不明白你是如何上传2MB的文件,但不能超过这个大小。你在这里使用什么Web服务器?(抱歉回复有点晚) - Yoann Chambonnet
你尝试过类似 ini_get('upload_max_filesize') 这样的方法来检查你的最大上传文件大小是否已经被配置文件正确设置了吗? - Yoann Chambonnet
@YoannChambonnet,你可以查看我所做的更新。 - Saiyan Prince
@koox00 我该如何检查它? - Saiyan Prince
显示剩余2条评论
2个回答

5
我遇到了同样的问题,通过增加UPLOAD_MAX_FILESIZE和POST_MAX_SIZE PHP设置来解决。前者应该比您正在上传的单个文件更大,后者应该比正在上传的两个(或更多)文件的总和更大。
这里有一个更好的解释,说明这对$_POST变量的影响,从而导致出现令牌不匹配异常:

http://laravel.io/forum/02-20-2014-l40-csrf-tokenmismatchexception-when-uploading-large-files

希望这对你有用,如果你还没有解决这个问题!

POST_MAX_SIZE 是我的罪魁祸首。 - Ben Chamberlin

-3

在你的表单中添加{!! csrf_token() !!}以生成CSRF令牌。

{!! Form::open(['url' => '/admin/products', 'autocomplete' => 'off', 'files' => true]) !!} @include('admin.products.product_general_form', ['submitButtonText' => '添加产品']) <input type="hidden" name="_token" value="{!! csrf_token() !!}"> {!! Form::close() !!}

当前在提交表单时,没有提供CSRF令牌,这是因为Laravel要求使用VerifyCsrfToken.php中间件。


感谢您的回复,但我想请您再次阅读我的问题。因为我已经清楚地说过,小于2MB的文件可以上传,而大于2MB的文件会抛出“TokenMismatchException”异常。另外,仅供参考,HTML表单门面默认包括“_token”。 - Saiyan Prince
你是否在你的PHP配置中增加了max_execution_time? - Muhammad Sumon Molla Selim
你为什么认为我需要在我的PHP配置中增加max_execution_time? - Saiyan Prince
由于您正在上传大文件,脚本执行可能需要更多时间来处理整个文件的上传。 - Muhammad Sumon Molla Selim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接