5

我一直在使用我的 Attachment 实体,该实体基于食谱如何在 Symfony 2.3 中使用 Doctrine 处理文件上传。

它运行良好,即使在功能测试中也是如此。然而,将它与 Doctrine DataFixtures 一起使用给我带来了问题。

[Symfony\Component\HttpFoundation\File\Exception\FileException]
The file "o-rly-copy.jpg" was not uploaded due to an unknown error.

这没有帮助,但是我确实运行php app/console doctrine:fixtures:load -v以显示堆栈跟踪,并且似乎异常不是在持久化方法上引发的,而是在$manager->flush()

Attachment::setFile()需要一个实例,UploadedFile所以我想知道是否有办法解决这个问题。

似乎错误发生在第 225 行Symfony\Component\HttpFoundation\File\UploadedFile

return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname())

因为文件已经在服务器上,所以is_uploaded_file()返回的条件。false

<?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);
        }
    }
}
4

2 回答 2

16

现在有一个更好的解决方案:

的构造函数UploadedFile有一个布尔$test参数,该参数禁用使用is_uploaded_file. 此参数已添加用于测试/夹具代码。

只需将其设置为true,isValid()检查UploadedFile将不再是问题。

例子:

// My data fixture code.
$test = true;
$userPhoto->setImageFile(new UploadedFile($photoDir . $photoFile, $photoFile, null, null, null, $test));
于 2018-01-26T12:09:56.693 回答
3

感谢 stof,解决方案是Attachment::setFile()(或者Document::setFile()如果使用食谱示例)提示UploadedFile的父类的实例,Symfony\Component\HttpFoundation\File\File,并在fixtures类中,创建一个新实例并将其传递给 setFile 方法

附件.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';
        }
    }

    //...
}

附件夹具.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);
        //...
    }
}
于 2013-09-24T13:49:49.027 回答