Symfony HttpFoundation UploadedFile "not uploaded due to unknown error" when using Doctrine DataFixtures
Solution 1
Thanks to stof, the solution is to make Attachment::setFile()
(or Document::setFile()
if using the cookbook example) hint for an instance of UploadedFile
's parent class, Symfony\Component\HttpFoundation\File\File
, and in the fixtures class, create a new instance and pass it to the setFile method
Attachment.php
<?php
namespace Acme\DemoBundle\Entity;
use Symfony\Component\HttpFoundation\File\File;
//...
class Attachment
{
/**
* Sets file.
*
* @param File $file
*/
public function setFile(File $file = null)
{
$this->file = $file;
// check if we have an old image path
if (isset($this->path)) {
// store the old name to delete after the update
$this->temp = $this->path;
$this->path = null;
} else {
$this->path = 'initial';
}
}
//...
}
AttachmentFixtures.php
<?php
namespace Acme\DemoBundle\DataFixtures\ORM;
use Symfony\Component\HttpFoundation\File\File;
//...
class AttachmentFixtures //...
{
//...
public function load(ObjectManager $manager)
{
//...
$imageFile = new File($pathToCopiedFile);
$imageAttachment = new Attachment();
$imageAttachment->setFile($imageFile);
//...
}
}
Solution 2
There is now a better solution:
The constructor of UploadedFile
has a boolean $test
parameter which disables the check using is_uploaded_file
. This parameter has been added for testing/fixture code.
Just set it to true and the isValid()
check of UploadedFile
will not be a problem anymore.
Example:
// My data fixture code.
$test = true;
$userPhoto->setImageFile(new UploadedFile($photoDir . $photoFile, $photoFile, null, null, null, $test));
Adam Elsodaney
Half-English + half-Egyptian, though I am mostly just an Englishman... I require milk in my tea. I regularly get my hands dirty and wear all development hats: Backend, Frontend, Database, DevOps, Design, UI, UX, QA, etc. With my core strength as a Symfony web developer. I was originally trained as an architect, but soon discovered I had a knack for web development through building by own site to promote my design work. Find me on SensioLabs Connect | Github (as myself) | Github (as ArchFizz) and on LinkedIn | Careers 2.0
Updated on June 23, 2022Comments
-
Adam Elsodaney almost 2 years
I've been using my Attachment entity based on the cookbook recipie How To Handle File Uploads With Doctrine in Symfony 2.3.
It works well, even in functional tests. However using it with Doctrine DataFixtures is causing me problems.
[Symfony\Component\HttpFoundation\File\Exception\FileException]
The file "o-rly-copy.jpg" was not uploaded due to an unknown error.This was not helpful, however I did run
php app/console doctrine:fixtures:load -v
to bring up a stack trace and it appears the exception is thrown not on the persisting method, but on$manager->flush()
Attachment::setFile()
requires an instance ofUploadedFile
so I wonder if there is a way round that.It appears the error occurs on line 225 of
Symfony\Component\HttpFoundation\File\UploadedFile
return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname())
The condition for
is_uploaded_file()
returnsfalse
because the file was already on the server.<?php /** * Prepopulate the database with image attachments. */ final class AttachmentFixtures extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface { private static $imageData = array( array( 'name' => "O RLY?", 'file' => "o-rly", 'type' => "jpg", ), //... ); public function getPathToImages() { return $this->container->get('kernel')->getRootDir() . '/../src/Acme/DemoBundle/Resources/public/default/images'; } public function getPathToUploads() { return $this->container->get('kernel')->getRootDir() . '/../web/uploads/fixtures'; } /** * {@inheritDoc} */ public function load(ObjectManager $manager) { $imageReferences = array(); $filesystem = $this->container->get('filesystem'); foreach (self::$imageData as $image) { $imageFilename = sprintf('%s.%s', $image['file'], $image['type']); $copiedImageFilename = sprintf('%s-copy.%s', $image['file'], $image['type']); $pathToImageFile = sprintf('%s/%s', $this->getPathToImages(), $imageFilename); try { $filesystem->copy($pathToImageFile, $pathToCopiedFile = sprintf('%s/%s', $this->getPathToUploads(), $copiedImageFilename)); $filesystem->chmod($pathToCopiedFile, 0664); } catch (IOException $e) { $this->container->get('logger')->err("An error occurred while copying the file or changing permissions."); } $imageFile = new UploadedFile( $pathToCopiedFile, // The full temporary path to the file $copiedImageFilename, // The original file name 'image/' . 'jpg' === $image['type'] ? 'jpeg' : $image['type'], // Mime type - The type of the file as would be provided by PHP filesize($pathToCopiedFile), null, null, true ); $imageAttachment = new Attachment(); $imageAttachment->setName($image['name']); $imageAttachment->setFile($imageFile); // Populate a reference array for later use $imageReferences['attachment-'.$image['file']] = $imageAttachment; $manager->persist($imageAttachment); } $manager->flush(); // <-- Exception throw here // Create references for each image to be used by other entities that // maintain a relationship with that image. foreach ($imageReferences as $referenceName => $image) { $this->addReference($referenceName, $image); } } }
-
Yassine CHABLI about 6 yearsthis is gonna delete the original file .while you have to deal with the tmp file .
-
famas23 about 4 yearsif test = true, then the original file will not be deleted ... In cas we want to delete the file ?