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
Related
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
I have a controller that generates an image and returns the image in the response.
use FOS\RestBundle\Controller\Annotations as Rest;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
...
/**
* #Rest\Get("/image/{name}")
*/
public function getImage($name) {
$imageService = $this->get('image.service');
$tempImage = $imageService->genImage($name);
return new BinaryFileResponse($tempImage);
}
This works great but temp image never gets deleted.
How do I delete the temp image after the response is sent?
I read though the implementation of BinaryFileResponse. Turns out there is a public method deleteFileAfterSend
I just need
return (new BinaryFileResponse($tempImage))->deleteFileAfterSend(true);
I'm facing following problem and can't seem to figure this one out.
I wrote an API endpoint accepting a POST with binary data (header: content-type:image/jpeg).
I know i can read out the raw string with file_get_content('php://input') or Laravel's $request->getContent().
PHP also has a function createimagefromstring($string) which also seems to read the string in correctly.
What i'd like to do is create an UploadedFile from this raw data , so that I can handle it with already written functions.
Is this possible?
Thank you in advance
I think I found it... Still curious if there are improvements that can be made..
$imgRaw = imagecreatefromstring( $request->getContent() );
if ($imgRaw !== false) {
imagejpeg($imgRaw, storage_path().'/tmp/tmp.jpg',100);
imagedestroy($imgRaw);
$file = new UploadedFile( storage_path().'/tmp/tmp.jpg', 'tmp.jpg', 'image/jpeg',null,null,true);
// DO STUFF WITH THE UploadedFile
}
You can try to use base64 encoding. Symfony have some nice stuff for this.
Your code will be smthng like this:
$base64Content = $request->request->get('base64Content'); // this is your post data
$yourFile = new UploadedBase64EncodedFile(new Base64EncodedFile($base64Content)); // this is an instance of UploadedFile
Hope it helps!
As per Laravel 8
Just follow the constructor:
* #param string $path The full temporary path to the file
* #param string $originalName The original file name of the uploaded file
* #param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
* #param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
* #param bool $test Whether the test mode is active
$file = new UploadedFile(
$pathIncludingFilename,
$fileName,
'image/jpeg',
null,
false
);
There is no need to manually create it, Symfony parses received $_FILES array for you. Http Request object has a FileBag property called $files with a get() method which returns an UploadedFile instance.
/** #var UploadedFile $file */
$file = $request->files->get('user-pictures-upload')[0];
$cmd = new UploadPictureCmd($file, $this->getUser()->getId());
Here is the example of generating images files using fzaninotto/faker in Symfony 4 Fixtures
class FileFixtures extends Fixture
{
private $faker;
private $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->faker = Factory::create();
$this->parameterBag = $parameterBag;
}
public function load(ObjectManager $manager)
{
$tempFixturesPath = $this->parameterBag->get('kernel.project_dir') . '/tmp';
if (!file_exists($tempFixturesPath)) {
mkdir($tempFixturesPath);
}
$fileName = $this->faker->image($tempFixturesPath, 640, 480, 'cats', false, true);
$file = new UploadedFile($tempFixturesPath . '/' . $fileName, $fileName, 'image/jpeg', null, null, true);
//do something with $file
}
}
If it counts for anything, this is how I did it in Laravel 5.4. In my case, I wanted to be able to easily resize an image and be able to do something like this.
request()->file('image')->resize(250, 250)->store('path/to/storage');
This is what I did to the UploadedFile class.
Illuminate\Http\UploadedFile.php ~this file ships with the Laravel framework
public function resize($w, $h) {
$image = Intervention::make($this)->fit($w, $h)->save($this->getPathname());
$filesize = filesize($this->getPathname());
return new static(
$this->getPathname(),
$this->getClientOriginalName(),
$this->getClientMimeType(),
$filesize,
null,
false
);
}
Using Intervention, I resized the image that is stored in the /tmp/ folder when files are uploaded and then I saved it in the same place. Now all I do after that is create an instance of UploadedFile so that I can keep using Laravel's methods on request()->file('image'). Hope this helps.
I'm working on the validation of one of my form and I need to check that the uploaded file is a pdf. I tried using a File constraint in my form, but it still let's me pass something that's not a pdf (a .txt for exemple).
Am I doing it wrong or should a use an other method to do that?
My form:
<?php
namespace AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;
Class FormUpdateCV extends AbstractType
{
public function buildForm(FormBuilderInterface $constructeur, array $options)
{
$format_fichier=new File(array(
'mimeTypes'=>'application/pdf',
'mimeTypesMessage'=>'Le fichier doit être un pdf'
));
$constructeur
->add('CV','file',array('label'=>'C.V.:', 'constraints'=>array($format_fichier)))
->add('mettreAJour','submit',array('label'=>'Mettre à jour'));
}
public function getName()
{
return 'update_CV';
}
}
You can add constraint directly in the entity. What do you think about this solution.
// src/Acme/BlogBundle/Entity/Author.php
namespace Acme\BlogBundle\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;
}
After trying some stuff, it seems like my previous condition does work. It's just that if I had, for exemple, a .pdf file and choose to change the extension to .txt, it still recognize it as a .pdf, but it still change the extention in my controller, so it's o.k. On the other side, if I change a .txt for a .pdf it still recognize the file as .txt, which is good since the file would read wright anyway.
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!