简体   繁体   English

Symfony维护文件上传的相对路径

[英]Symfony maintaining relative path for file uploads

I'm using Symfony 4.1, and I had a hard time getting the relative/fullpath to work as I want it. 我使用的是Symfony 4.1,我很难让相对/全路径按我的意愿工作。

In my database, I have a Customer entity with an attribute called photo. 在我的数据库中,我有一个Customer实体,其属性称为photo。

<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * @ORM\Entity(repositoryClass="App\Entity\CustomerRepository")
 * @ORM\Table("Customer")
 */
class Customer {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

     /**
       * @ORM\Column(type="string", nullable=true)
       *
       * @Assert\File(mimeTypes={ "image/png","image/jpeg" })
       */
     private $photo;

     public function getPhoto(): ?string
     {
        return $this->photo;
     }

     public function setPhoto(?string $photo): self
     {
        $this->photo = $photo;
        return $this;
     }

This makes sense and when I save the Customer with a Photo upload, it saves the photo in the database and on the filesystem as I expect. 这很有道理,当我用上载照片的方式保存客户时,它会将照片按预期保存在数据库和文件系统中。

In the database, the photo column will be set to something like '010925c8c427bddca9020197212b64af.png' 在数据库中,“照片”列将设置为“ 010925c8c427bddca9020197212b64af.png”

That's what I want, so it's all good. 那就是我想要的,所以一切都很好。

The problem came up when I was trying to update an existing Customer entity. 当我尝试更新现有的客户实体时出现问题。 Customer->getPhoto() will return the relative path file name '010925c8c427bddca9020197212b64af.png.' Customer-> getPhoto()将返回相对路径文件名“ 010925c8c427bddca9020197212b64af.png”。

But the form doesn't pass validation, it says that this file doesn't exist. 但是该表单未通过验证,它表示该文件不存在。

$em = $this->getDoctrine()->getManager();
$custRepo = $em->getRepository('App:Customer');
$customer = $custRepo->findOneById($id);
$custForm = $this->createForm(CustomerType::class, $customer);
$custForm->handleRequest($request);
if ($custForm->isSubmitted() && $custForm->isValid()) {
    $em->flush();
}

It fails because the validation doesn't look in the photos directory. 失败是因为验证不在photos目录中。

Here's my solution, which does work, but it seems too hackish. 这是我的解决方案,它确实有效,但似乎过于骇人听闻。 I wasn't wondering if someone had a more elegant approach to this. 我想知道是否有人对此有更优雅的方法。

$em = $this->getDoctrine()->getManager();
$custRepo = $em->getRepository('App:Customer');
$customer = $custRepo->findOneById($id);
$customer->setPhoto(new File($this->getParameter('photos_dir') .'/' . $customer->getPhoto()));
$custForm = $this->createForm(CustomerType::class, $customer);
$custForm->handleRequest($request);
if ($custForm->isSubmitted() && $custForm->isValid()) {
    $photoPathParts = explode('/', $customer->getPhoto());
    $customer->setPhoto(array_pop($photoPathParts));
    $em->flush();
}

I'm getting the fullpath for the photo and updating the entity I'm currently work on. 我正在获取照片的完整路径并更新我当前正在处理的实体。 That gets the form validation to pass, but if I just save it, the path in the db is updated with the full path to the photo. 这样就可以通过表单验证,但是如果我只保存它,数据库中的路径将更新为照片的完整路径。 That's not what I want, so I reset the photo to the relative path filename. 那不是我想要的,所以我将照片重置为相对路径文件名。

/**
 * @ORM\Column(type="string", nullable=true)
 *
 * @Assert\File(mimeTypes={ "image/png","image/jpeg" })
 */
 private $photo;

Look at this example how to upload image. 看这个例子,如何上传图片。 The image is in a separate entity , you can relate it to customer OneToOne. 该图像位于单独的实体中,您可以将其与客户OneToOne相关。

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * Image
 *
 * @ORM\Table(name="image")
 * @ORM\Entity(repositoryClass="App\Repository\ImageRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Image
{
/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;
/**
 * @ORM\Column(name="extension", type="string", length=180)
 */

private $name;
/**
 * @Assert\Image()
 */
public $file;

private $tempFilename;

public function getId(): ?int
{
    return $this->id;
}

public function getName(): ?string
{
    return $this->name;
}

public function setName(string $name): self
{
    $this->name = $name;
    return $this;
}

public function setFile(UploadedFile $file)
{
    $this->file = $file;
    if (null !== $this->extension) {
        $this->tempFilename = $this->name;
        $this->extension = null;
        $this->name = null;
    }
}

public function getFile()
{
    return $this->file;
}

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function preUpload()
{
    if (null === $this->file) {
        return;
    }
    $extension = $this->file->guessExtension();
    $this->name = md5(uniqid('', true)) . '.' . $extension;
}

/**
 * @ORM\PostPersist()
 * @ORM\PostUpdate()
 */
public function upload()
{
    if (null === $this->file) {
        return;
    }
    if (null !== $this->tempFilename) {
        $oldFile = $this->getUploadRootDir() . '/' . $this->tempFilename;
        if (file_exists($oldFile)) {
            unlink($oldFile);
        }
    }
    $this->file->move($this->getUploadRootDir(), $this->name);
}

/**
 * @ORM\PreRemove()
 */
public function preRemoveUpload()
{
    $this->tempFilename = $this->getUploadRootDir() . '/' . $this->name;
}

/**
 * @ORM\PostRemove()
 */
public function removeUpload()
{
    if (file_exists($this->tempFilename)) {
        unlink($this->tempFilename);
    }
}

//folder
public function getUploadDir()
{
    return 'uploads/photos';
}

// path to folder web
protected function getUploadRootDir()
{
    return __DIR__ . '/../../public/' . $this->getUploadDir();
}

public function getWebPath()
{
    return $this->getUploadDir() . '/' . $this->getName();
}

}

ImageFormType ImageFormType

NB: You should use the public attribue $file in the formType 注意:您应该使用formType的公共属性$ file

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('file', FileType::class, array(
            'label'=> false,
        ))
    ;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM