10000 Form using Validator Constraint File - Max File Size not validating correctly, element returns NULL · Issue #13291 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
8000

Form using Validator Constraint File - Max File Size not validating correctly, element returns NULL #13291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
0mars opened this issue Jan 6, 2015 · 13 comments

Comments

@0mars
Copy link
0mars commented Jan 6, 2015

When submitting a file greater than the max file size, and then trying to get the UploadedFile, it returns null instead of an UploadedFile instance.

use Symfony\Component\Validator\Constraints\File;
// adding form element
$form->add('my_file', 'file', [
                'required' => true,
                'constraints' => [
                    new File([
                        'maxSize' => '5M',
                        'mimeTypes' => [
                            'application/pdf',
                            'application/x-pdf',
                        ],
                        'mimeTypesMessage' => 'Please upload a valid PDF',
                    ])
                ]
            ]);
// in controller
$form->submit($this->getRequest()->request->all());
var_dump($form->get('my_file')->getData());

Actual:

NULL

Expected:

Symfony\Component\HttpFoundation\File\UploadedFile Object
@lscholten
Copy link

I tried to recreate this issue in a fork of the Symfony Standard Edition (v2.6)

I came to the following conclusions, which are summarized in the DefaultController (https://github.com/lscholten/symfony-standard-issue-13291/blob/2.6/src/AppBundle/Controller/DefaultController.php)

You passed all request data to the submit function:

$form->submit($this->getRequest()->request->all());

This won't work correctly since all request data (not just the form data) is submitted. I fixed it and recreated your issue by using:

$form->submit($this->getRequest()->request->get($form->getName()));

And indeed, the var_dump resulted in NULL.

What happens is that $this->getRequest()->request only contains the actual form data, and not the file data, this is available in $this->getRequest()->files. To make it work, I submitted the file data together with the request data:

$form->submit(
    array_merge(
        $this->getRequest()->request->get($form->getName()),
        $this->getRequest()->files->get($form->getName())
    )
);

However, this could've all been avoided when using the recommended method $form->handleRequest(...) as I've demonstrated in the last action. (http://symfony.com/doc/current/book/forms.html#book-form-handling-form-submissions)

$form->handleRequest($request);  // $request is in injected into the action

Conclusion: probably not a Symfony bug

@0mars
Copy link
Author
0mars commented Jan 6, 2015

The weird thing is that, if the file does not exceed max size you don't need to do an array_merge, it works perfectly, and if the mime type validation fails, its also reported on the form errors, but its not the case for maxSize

@jakzal
Copy link
Contributor
jakzal commented Jan 7, 2015

@lscholten excellent analysis!

@humanoyd I just tried on @lscholten's fork and it indeed works as expected, consistently, no matter what the file size is. Could you please try it on that fork and alter the code so it shows how to reproduce your problem?

@0mars
Copy link
Author
0mars commented Jan 18, 2015

Checkedout out the code, and tried
expected-behavior: With a PDF exceeds max size (31 MB)

/**
     * @Route("/app/expected-behaviour", name="expected_behaviour")
     */
    public function expectedBehaviourAction()
    {
        $form = $this->createFileForm();

        if ($this->getRequest()->getMethod() === "POST") {
            $form->submit(
                array_merge(
                    $this->getRequest()->request->get($form->getName()),
                    $this->getRequest()->files->get($form->getName())
                )
            );

            var_dump($form->get('my_file')->getData());
        }

        return $this->render('default/index.html.twig', ['form' => $form->createView()]);
    }

Getting:

Warning: array_merge(): Argument #1 is not an array
500 Internal Server Error - ContextErrorException 

@jakzal
Copy link
Contributor
jakzal commented Jan 19, 2015

@humanoyd what's upload_max_filesize set to in your php.ini?

@0mars
Copy link
Author
0mars commented Jan 25, 2015

UPDATE: if the file exceeds upload_max_filesize, exception is thrown:

Warning: array_merge(): Argument #1 is not an array
500 Internal Server Error - ContextErrorException 

Only $form->handleRequest($request); works properly with files greater than the upload_max_filesize

@0mars
Copy link
Author
0mars commented Jan 26, 2015

Here is the analysis of 3 cases

    private function createFileForm()
    {
        return $this->createFormBuilder()
            ->add('my_file', 'file', [
                'required' => true,
                'constraints' => [
                    new File([
                        'maxSize' => '2M',
                        'mimeTypes' => [
                            'application/pdf',
                            'application/x-pdf',
                        ],
                        'mimeTypesMessage' => 'Please upload a valid PDF',
                    ])
                ]
            ])
            ->add('field2','text',['required'=>true])
            ->add('submit', 'submit')
            ->getForm();
    }
    /**
     * @Route("/app/original-not-working2", name="original_not_working")
     */
    public function orginalNotWorkingAction()
    {
        $form = $this->createFileForm();

        if ($this->getRequest()->getMethod() === "POST") {
            $form->submit($this->getRequest());
            var_dump($form->get('my_file')->getData());
        }

        return $this->render('default/index.html.twig', ['form' => $form->createView()]);
    }

Using
upload_max_filesize = 8M

1. Case 1

File: some-file.odt
size: 1.2KB

Expected:
Error: Please upload a valid PDF
Actual:
Error: Please upload a valid PDF

2. Case 2:

File size greater than validation rule, but less than php's upload_max_filesize
File: some-file2.odt
size: 7MB
Expected:
The file is too large. Allowed maximum size is 2 MB.
Actual:
The file is too large. Allowed maximum size is 2 MB.

3. Case 3:

File size greater than post_max_size
File: some-file3.odt
size: 11MB
Expected:
The file is too large. Allowed maximum size is 2 MB.
Actual:
Nothing, No errors, even on other form fields

@0mars
Copy link
Author
0mars commented Jan 26, 2015

@jakzal
Copy link
Contributor
jakzal commented Jan 26, 2015

@humanoyd excellent! I'll have a look later today or tomorrow.

@jakzal
Copy link
Contributor
jakzal commented Jan 30, 2015

Looks like it was introduced when moving post_max_size from FormValidator to request handlers in #11924. As @humanoyd noticed when using submit() the form passes validation, even though the uploaded file was bigger than the allow post size. It's because if post_max_size is exceeded, both $_POST and $_GET are empty, and technically no fields are passed to submit().

In both cases (handleRequest() and submit()) a warning is triggered:

Warning: POST Content-Length of 20824840 bytes exceeds the limit of 8388608 bytes in Unknown on line 0

@webmozart webmozart added the Bug label Apr 24, 2015
0mars added a commit to 0mars/symfony that referenced this issue Oct 2, 2015
…eRequest

Fixes the issue with uploaded files exceeding post_max_size,
and form marked valid with empty fields
0mars added a commit to 0mars/symfony that referenced this issue Oct 2, 2015
…eRequest

Fixes the issue with uploaded files exceeding post_max_size,
and form marked valid with empty fields
0mars added a commit to 0mars/symfony that referenced this issue Oct 2, 2015
…eRequest

When the argument of Form::submit is a Request object it forwards to
Form::HandleRequest.
Fixes the issue with uploaded files exceeding post_max_size,
and form marked valid with empty fields.
0mars added a commit to 0mars/symfony that referenced this issue Oct 3, 2015
0mars added a commit to 0mars/symfony that referenced this issue Oct 3, 2015
0mars added a commit to 0mars/symfony that referenced this issue Oct 4, 2015
@Tobion
Copy link
Contributor
Tobion commented Oct 6, 2015

To sum up: You have to use handleRequest to get max post size validation logic because it's part of the request handling. At submit time it's not done anymore because if the max post size is exceeded, the post content is empty. This is also why why you have the above Warning: array_merge(): Argument #1 is not an array 500 Internal Server Error - ContextErrorException in your own code.
The only problem is that the max post size validation is missing when using submit($request) as trying to fix in #16088. But this approach is deprecated anyway. Feel free to open a new issue or PR for this.

@Tobion Tobion closed this as completed Oct 6, 2015
@MgFrobozz
Copy link
MgFrobozz commented Jul 7, 2016

I've encountered the same problem when the file size exceeds upload_max_filesize and when using handleRequest. Config details below.

In HttpFoundationRequestHandler.php::handleRequest,
$this->serverParams->getPostMaxSize() returns 576716800
$this->serverParams->getContentLength() returns null
and it never reaches $form->addError(...)

In ServerParams.php::getContentLength,
$_SERVER['CONTENT_LENGTH'] is not set
however, print_r($_SERVER) shows
[HTTP_CONTENT_LENGTH] => 600001284

I think getContentLength needs to check both CONTENT_LENGTH and HTTP_CONTENT_LENGTH.

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Util/ServerParams.php shows the same issue

Submitted as #19311

Config:
symfony 2.5.12
Ubuntu 14.04.4 LTS

@darius-v
Copy link
darius-v commented Aug 14, 2018

how handleRequest() works for you? For me it goes into block where is such comment " // Don't submit the form if it is not present in the request" .

I checked form name is 'form'.

here is what I have tried -

            ->add('file', FileType::class, [
                'required' => true,
                'constraints' => [
                    new File([
                        'mimeTypes' => [
                            'application/pdf',
                            'application/msword',
                            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                            'application/vnd.ms-excel',
                            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                            'image/gif',
                            'image/png',
                            'image/jpeg',
                            'application/vnd.oasis.opendocument.text',
                            'application/vnd.oasis.opendocument.spreadsheet'
                        ]
                    ]),
                    new Count(['min' => 1, 'max' => 1])
                ]
            ])
            //->add('submit', SubmitType::class)
            ->getForm();


      


//        $form->handleRequest($request);
//        $form->submit($request->request->all(), false);
        $form->submit($request->files->get($form->getName()));```

And could not make did not help

Update:
Here is how I solved: https://stackoverflow.com/questions/51841384/symfony-3-4-file-is-not-validated-when-using-createformbuilder/51841872#51841872

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants
0