8

如何在没有表单的情况下使用VichUploaderBundle上传文件?

我在某个目录中有文件(例如web/media/tmp/temp_file.jpg

如果我试试这个:

$file = new UploadedFile($path, $filename);

$image = new Image();
$image->setImageFile($file);

$em->persist($image);
$em->flush();

我有这个错误:

由于未知错误,文件“temp_file.jpg”未上传。

我需要从远程 url 上传文件。因此,我将文件上传到目录tmp(使用 curl),然后我一直尝试将其注入 VichUploadBundle(如上所示)。

4

4 回答 4

11

接受的答案不正确(不再?)。根据使用文档 ,您确实可以在File不使用 Symfony 的表单组件的情况下手动上传:

/**
 * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
 * of 'UploadedFile' is injected into this setter to trigger the  update. If this
 * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
 * must be able to accept an instance of 'File' as the bundle will inject one here
 * during Doctrine hydration.
 *
 * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
 */
public function setImageFile(File $image = null)
{
    $this->imageFile = $image;

    if ($image) {
        // It is required that at least one field changes if you are using doctrine
        // otherwise the event listeners won't be called and the file is lost
        $this->updatedAt = new \DateTime('now');
    }
}
于 2015-11-29T12:43:43.633 回答
4

您应该使用Symfony\Component\HttpFoundation\File\UploadedFile而不是File

$file = new UploadedFile($filename, $filename, null, filesize($filename), false, true);

VichUploaderBundle将处理这个对象。

于 2016-08-12T13:40:16.880 回答
2

结合答案并解决 VichUploader 的问题并在活动期间inject_on_load: true更改。updatedAtpostLoad

问题说明

由于 Doctrine ORM 不监视 VichUploader 映射属性,因此您需要确保至少更改 ORM 管理的属性之一以触发VichUploader 用于管理文件引用的事件prePersist。 这通常通过在文件设置器中使用 DATETIME 列来完成,但可以是由 ORM 管理的任何属性。preUpdate
updatedAt

postLoad事件设置器File实例问题

验证UploadedFile提供给映射属性设置器方法的实例将确保在表单提交期间或手动提供时updatedAt更改,而不是在事件期间更改 - 其中 VichUpload 为相同的映射设置器方法提供实例。如果您在 Doctrine 加载对象实例并因此对其进行管理时调用,这将导致视图中的值发生更改并可能更改数据库值。postLoadFileupdatedAt$em::flush()Image

应用\实体\图像

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class Image
{

    /**
     * @var \DateTime
     * @ORM\Column(name="updated_at", type="datetime")
     */
    private $updatedAt;

    /**
     * @var \Symfony\Component\HttpFoundation\File\File
     * @Vich\UploadableField(mapping="your_mapping", fileNameProperty="image")
     */
    private $imageFile;

    /**
     * @var string|null
     * @ORM\Column(name="image", type="string", length=255, nullable=true)
     */
    private $image;

    public function __construct()
    {
        $this->updatedAt = new \DateTime('now');
    }

    //...

    public function setImageFile(File $image = null)
    {
        $this->imageFile = $image;
        if ($image instanceof UploadedFile) {
            $this->updatedAt = new \DateTime('now');
        }
    }

}


UploadedFile然后,您可以通过实例化一个对象并将error参数设置为null并将test参数设置为来手动定义要在实体中使用的文件true,这将禁用验证UPLOAD_ERR_OKis_uploaded_file() [sic]

Symfony <= 4.0

use Symfony\Component\HttpFoundation\File\UploadedFile;

$file = new UploadedFile($path, $filename, null, filesize($path), null, true);

Symfony 4.1+

在 Symfony 4.1 及更高版本中,文件大小参数已被弃用。

use Symfony\Component\HttpFoundation\File\UploadedFile;

$file = new UploadedFile($path, $filename, null, null, true);

现在您可以使用手动上传的文件成功持久化和/或刷新您的实体。

$image = new Image();
$image->setImageFile($file);

$em->persist($image);
$em->flush();
于 2020-10-21T19:18:31.467 回答
1

简短的回答:VichUploaderBundle不支持在不使用 Symfony 表单组件的情况下上传文件。

我需要从远程 url 上传文件。所以我将文件上传到 tmp 目录(使用 curl),然后我继续尝试将其注入到 VichUploadBundle(如上所示)。

在这种情况下,您不需要上传,您需要下载。这不是我们VichUploaderBundle应该做的。

于 2015-08-05T11:47:33.777 回答