Symfony2 - Validate file size before uploading it - php

I'm validating the file size when a user uploads a file, but I'm getting weird results when the file is too large:
Controller:
// Attachments form
$form = $this->createFormBuilder()
->add('file', 'file', array('label' => ' ',
))
->getForm();
if ($this->getRequest()->isMethod('post') && $form->bind($this->getRequest())->isValid()) {
$uploadedFile = $form['file']->getData();
...
}
Entity:
namespace Pro\Bundle\Entity;
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
/**
* #ORM\Entity
* #ORM\Table(name="file")
*/
class File
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
//more properties...
/**
* #var SymfonyFile
* #Constraints\File(maxSize=2000000) // <2 MB
*/
private $filesystemFile;
function __construct(SymfonyFile $file, $name)
{
$this->created = new \DateTime;
$this->setFilesystemFile($file);
$this->name = $name;
}
//more methods...
function setFilesystemFile(SymfonyFile $file)
{
$this->filesystemFile = $file;
}
}
So when a user submits a file, the isValid method check the file size. If it is larger that 2000000B it will throw an error. But I'm getting weird results:
In localhost (upload_max_filesize = 2M, post_max_size = 2M):
If the file is too large I get two errors:
Token not valid.
The uploaded file is too large.
In VPS (upload_max_filesize = 2M, post_max_size = 2M):
If the file is too large, first try to upload the file, and then an Internal Server Error is thrown. Looking at the logs I can see the error is due to the invalid entity, because the file is too large. So it seems like it's trying to move the file, even if it's too large...

Did you try having a function like this in the Entity file and add a validation using validation.yml file?
public function isFilesystemFile()
{
$valid = false;
//do the validation such as file size is too large.
//then set the valid flag accordingly
return $valid;
}
In validation.yml file
Pro\Bundle\Entity\FilesystemFile:
getters:
FilesystemFile:
- "True": { message: "File size is too large." }
Hope this helps.
Cheers!

Related

How to access uploaded files in frontend in the controller in Typo3?

In typo3 i created a domain model for persons with the extension builder. One of the properties should be a profile picture. I need some help on how to pass the uploaded file to my controller.
The form for creating, editing looks something like this:
<f:form action="update" arguments="{picture:picture}" name="person" object="{person}" >
<f:form.upload name="picture" class="imageupload" />
<f:form.textfield property="firstName" />
<f:form.textfield property="lastName" />
<f:form.submit value="Save" />
the update action in the controller:
public function updateAction(\Vendor\Persons\Domain\Model\Person $person, $picture) {
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$storage = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getDefaultStorage();
$file = $storage->getFolder('images')->addFile($picture);
$fileReference = $objectManager->get(\Vendor\Persons\Domain\Model\FileReference::class);
$fileReference->setFile($file);
$person->setPicture($fileReference);
$this->personRepository->update($person);
}
the FileReference Class:
class FileReference extends \TYPO3\CMS\Extbase\Domain\Model\FileReference {
/**
* uid of a sys_file
*
* #var integer
*/
protected $originalFileIdentifier;
/**
* setOriginalResource
*
* #param \TYPO3\CMS\Core\Resource\FileReference $originalResource
* #return void
*/
public function setOriginalResource(\TYPO3\CMS\Core\Resource\FileReference $originalResource) {
$this->originalResource = $originalResource;
$this->originalFileIdentifier = (int)$originalResource->getOriginalFile()->getUid();
}
/**
* setFile
*
* #param \TYPO3\CMS\Core\Resource\File $falFile
* #return void
*/
public function setFile(\TYPO3\CMS\Core\Resource\File $falFile) {
$this->originalFileIdentifier = (int)$falFile->getUid();
}
}
When i just hardcode a path to an image inside the addFile() function in the update action, everything seems to work, the file gets copied to fileadming and a filereference is created. However i have no idea on how to access the uploaded image from the form upload. I'm not even sure if the image is uploaded at all.
First of all, your form need to set to enctype="multipart/form-data". This allows the form to submit your uploaded files.
Then, you should change your property to <f:form.upload property="picture.originalResource" class="imageupload" /> to assign your file automaticaly to your picture refrence.
If you want to handle the upload by yourself can take an look on following code I used for TYPO3 8.7:
# Set target Folder
$mediaFolder = 'path/to/images';
$storage = $this->storageRepository->findByUid(1);
# check if target folder exist or create it
if ($storage->hasFolder($mediaFolder)) {
$targetFolder = $storage->getFolder($mediaFolder);
} else {
$targetFolder = $storage->createFolder($mediaFolder);
}
# add uploaded file
$imageFile = $targetFolder->addUploadedFile($picture, DuplicationBehavior::RENAME);
# FileReference is the instance of your extension
/** #var FileReference $imageFileReference */
$imageFileReference = $this->objectManager->get(FileReference::class);
$imageFileReference->setOriginalResource($imageFile);
$imageFileReference->setPid($person->getPid());
$person->setPicture($imageFileReference);

remove Exiff from UploadedFile Symfony

I have form that use to upload picture.
I can't save this picture on my server, But I send it to another service ( external)
I have to encode base 64
my code is:
$base_img = base64_encode(file_get_contents($data["image"]));
where $data['image'] is UploadedFile
How can Remove all Exiff from $data['image'] before encode?
Recently I needed exactly that and I achieved it with passing $uploadedFile->getRealPath() to the Imagick. Complete function:
/**
* #param UploadedFile $uploadedFile
* #throws \ImagickException
*/
public function stripMeta(UploadedFile $uploadedFile): void
{
$img = new Imagick($uploadedFile->getRealPath());
$profiles = $img->getImageProfiles("icc", true);
$img->stripImage();
if(!empty($profiles)) {
$img->profileImage("icc", $profiles['icc']);
}
$img->writeImage($uploadedFile->getRealPath());
}
I took saving icc profile idea from comments here: https://www.php.net/manual/en/imagick.stripimage.php

SilverStripe 4 - Save uploaded file as Member extension property

I'm trying to save an uploaded file via AJAX request to a page controller, as a Member extension property.
I got a Member DataExtension that implements a File property with a many_many relation, like this:
My Member Extension
[...]
/**
* Classe Utente - Estensione
*/
class UtenteExtension extends DataExtension
{
// Dichiarazione Proprietà
private static $many_many = [
'AllegatiUpload' => File::class, // this field should save users file uploads
[...]
];
private static $owns = [
'AllegatiUpload',
[...]
];
[...]
The Controller involved:
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\ErrorPage;
use SilverStripe\Assets\Folder;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Upload;
use SilverStripe\Security;
use SilverStripe\Security\Group;
use SilverStripe\Assets\Storage\AssetStore;
/**
* Classe Controller Utente - Dashboard
*/
class UtenteDashboardController extends PageController
{
// Dichiarazione Proprietà
private static $allowed_actions = [
'carica'
];
/**
* Funzione gestione validazione ed invio form caricamento
* #param HTTPRequest $request Richiesta HTTP
* #return HTTPResponse Risposta HTTP
*/
public function carica(SS_HTTPRequest $request) {
if (!$request->isAjax()) {
return ErrorPage::response_for(404);
} else if (!$request->isPOST()) {
return $this->httpError(400, 'Metodo POST richiesto');
} else {
$documento = $request->postVar('documento'); // File data sent by FormData JS API
if (!isset($documento)) {
return $this->httpError(500, 'Dati richiesti mancanti');
} else {
// User check
$utente = Security::getCurrentUser();
if ($utente->inGroup(Group::get()->filter('Code', 'clienti')->first()->ID)) {
// File uploading
$cartellaUpload = 'clienti/'. strtolower($utente->Surname) .'/uploads';
Folder::find_or_make($cartellaUpload);
// I tried with the official guide approach, with this line - with no results
//$utente->AllegatiUpload()->setFromLocalFile($cartellaUpload, documento, AssetStore::CONFLICT_OVERWRITE);
// Then I tried with this approach
$file = File::create();
$upload = Upload::create();
$upload->loadIntoFile($documento, $file, $cartellaUpload);
// Upload check
if ($upload->isError()) {
return $this->httpError(400, 'Errore di caricamento file');
} else {
// Relate the file to the destinaion user field
$utente->{'AllegatiUpload.ID'} = $upload->getFile()->ID;
// Update user
$utente->write();
return new HTTPResponse;
}
} else {
return $this->httpError(401, 'Utente non abilitato');
}
}
}
}
}
I'm stuck in the process in order to pair the file with the correct Member. I think I missing the correct syntax, because I'm working with a many_many relation and this one doesn't fit it:
// Relate the file to the destinaion user field
utente->{'AllegatiUpload.ID'} = $upload->getFile()->ID;
I tried too with an approach like this:
$allegato = $utente->AllegatiUpload();
$allegato->setField('Documento', $upload->getFile()->ID);
$allegato->write();
But I receive this exception:
[Emergency] Uncaught BadMethodCallException: Object->__call(): the method 'write' does not exist on 'SilverStripe\ORM\ManyManyList'
Maybe I must convert AllegatiUpload to a DataObject first, then adding a File property inside it in order to avoid this?
You add new items to relations with the $object->RelationName()->add($item) syntax, in your case:
$utente->AllegatiUpload()->add($file);
reference https://docs.silverstripe.org/en/4/developer_guides/model/relations/#adding-relations

XenForo Avatar upload fails, $image == false - PHP7

I'm stumped on a XenForo 1.5.7 / php7 issue. I've read that tempnam() was changed as of php7 (based on temp dir permissions), but I've chmod'd the directory as that link states, still to no avail.
I printed out $newTempFile which returns /var/www/forum/internal_data/temp/xfJ9FLyG (looks correct). It's the next line, the $image variable, that does not get set, and then throws the error in the if() below.
$newTempFile = tempnam(XenForo_Helper_File::getTempDir(), 'xf');
$image = XenForo_Image_Abstract::createFromFile($fileName, $imageType);
if (!$image)
{
throw new XenForo_Exception(new XenForo_Phrase('image_could_be_processed_try_another_contact_owner'), true);
}
Here is the code for createFromFile() in Image\Abstract.php:
/**
* Creates an image from an existing file.
*
* #param string $fileName
* #param integer $inputType IMAGETYPE_XYZ constant representing image type
*
* #return XenForo_Image_Abstract|false
*/
public static function createFromFileDirect($fileName, $inputType)
{
throw new XenForo_Exception('Must be overridden');
}
...
public static function createFromFile($fileName, $inputType)
{
$class = self::_getDefaultClassName();
return call_user_func(array($class, 'createFromFileDirect'), $fileName, $inputType);
}
Because it looks like createFromFileDirect() is called from createFromFile(), my thought was that a "Must be overriden" error would be thrown, but this doesn't appear to be the case.
Any ideas?

How to know uploaded file size on symfony 3?

i use FOSRestbundle to manage my api. I implemented a action to upload a file on symfony that it's working well. But the problem is that i need to obtain the file size... My action get the file on this way:
$uploadedfile = $request->files->get('file');
this obtains an array of all files that i upload.
Reading the doc of symfony for the $uploadedfile object, there is a method called:
getClientSize()
so i used and always return 0:
$fileSize = $uploadedfile->getClientSize();
There are another way to get the file size? I'm doing something wrong?
Thanks a lot.
how about the solution here?
http://symfony.com/doc/current/reference/constraints/File.html#maxsize
// src/AppBundle/Entity/Author.php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* #Assert\File(
* maxSize = "1024k",
* mimeTypes = {"application/pdf", "application/x-pdf"},
* mimeTypesMessage = "Please upload a valid PDF"
* )
*/
protected $bioFile;
}
you might have to create an entity for that, if you have not done so.
So if you want to use validation in your controller, you would do something like
// ...
use Symfony\Component\HttpFoundation\Response;
use AppBundle\Entity\Author;
// ...
public function authorAction()
{
$author = new Author();
// ... do something to the $author object
$validator = $this->get('validator');
$errors = $validator->validate($author);
if (count($errors) > 0) {
$errorsString = (string) $errors;
return new Response($errorsString);
}
return new Response('The author is valid! Yes!');
}
you can test it, by uploading a file larger than the maxsize, set in your given Author Entity in that case you would get the message "Please upload a valid PDF"
Have you successfully moved the file into the intended folder? if you have, you can just call a native php function filesize().
http://php.net/manual/en/function.filesize.php

Categories