问题描述:

I'm beginning with Symfony and I'm stuck with multiple upload.

I can upload just one file and I try to modify this code for multiple upload.

Here's my error :

Expected argument of type "Symfony\Component\HttpFoundation\File\UploadedFile", "array" given

Here's my code :

ImageArticleType:

$builder

->add('file', 'file', array('label' => 'Choisir mes images', 'multiple'=> true))

;

And my Entity ImageArticle.php

<?php

namespace AD\PlatformBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Component\HttpFoundation\File\UploadedFile;

use Symfony\Component\Validator\Constraints as Assert;

/**

* ImageArticle

*

* @ORM\Table()

* @ORM\Entity()

* @ORM\HasLifecycleCallbacks

*/

class ImageArticle

{

/**

* @var integer

*

* @ORM\Column(name="id", type="integer")

* @ORM\Id

* @ORM\GeneratedValue(strategy="AUTO")

*/

private $id;

/**

* @var string

*

* @ORM\Column(name="url", type="string", length=255)

*/

private $url;

/**

* @var string

*

* @ORM\Column(name="alt", type="string", length=255)

*/

private $alt;

/**

* @var File

*

* @Assert\File(

* maxSize = "1M",

* mimeTypes = {

* "image/jpeg",

* "image/gif",

* "image/png",

* },

* maxSizeMessage = "La taille maximum du fichier doit etre infrieur ou gale 1MB. Pour reduire sa taille vous pouvez utiliser le site : compressjpeg.com",

* mimeTypesMessage = "Seulement les fichiers .jpeg / .gif /.png sont accepts"

* )

*/

private $file;

private $tempFileName;

public function getFile()

{

return $this->file;

}

public function setFile(UploadedFile $file)

{

$this->file = $file;

if (null !== $this->url)

{

$this->tempFileName = $this->url;

$this->url=null;

$this->alt=null;

}

}

/**

* Get id

*

* @return integer

*/

public function getId()

{

return $this->id;

}

/**

* Set url

*

* @param string $url

*

* @return ImageArticle

*/

public function setUrl($url)

{

$this->url = $url;

return $this;

}

/**

* Get url

*

* @return string

*/

public function getUrl()

{

return $this->url;

}

/**

* Set alt

*

* @param string $alt

*

* @return ImageArticle

*/

public function setAlt($alt)

{

$this->alt = $alt;

return $this;

}

/**

* Get alt

*

* @return string

*/

public function getAlt()

{

return $this->alt;

}

/**

* @ORM\PrePersist()

* @ORM\PreUpdate()

*/

public function preUpload()

{

if (null === $this->file)

{

return;

}

//On add un extension pour le fichier.

$this->url = $this->file->guessExtension();

//Le alt est le nom du fichier du client.

$this->alt= $this->file->getClientOriginalName();

}

/**

*

* @ORM\PostPersist()

* @ORM\PostUpdate()

*

*/

public function upload()

{

if(null=== $this->file)

{

return;

}

//Si ancien fichier on supprime

if(null !== $this->tempFileName)

{

$oldFile = $this->getUploadRootDir().'/'.$this->id.'.'.$this->tempFileName;

if (file_exists($oldFile))

{

unlink($oldFile);

}

}

//On deplace

$this->file->move

(

$this->getUploadRootDir(),

$this->id.'.'.$this->url

);

}

/**

*@ORM\PreRemove()

*/

public function preRemoveUpload()

{

$this->tempFileName = $this->getUploadRootDir().'/'.$this->id.'.'.$this->url;

}

/**

*

* @ORM\PostRemove()

*/

public function removeUpload()

{

if(file_exists($this->tempFileName))

{

unlink($this->tempFileName);

}

}

public function getUploadDir()

{

return 'upload/img/';

}

protected function getUploadRootDir()

{

return __DIR__.'/../../../../web/'.$this->getUploadDir();

}

public function __toString()

{

return $this->getUploadDir().$this->id.'.'.$this->getUrl();

}

/**

* Set source

*

* @param string $source

*

* @return Image

*/

}

I was thinking about a simple foreach loop but it doesn't work...

网友答案:

Uploading files with multiple option can be a little bit tricky. With multiple = false option your $file property in your entity class will return single UploadedFile instance, with multiple = true it returns array of UploadedFile instances when you call $entity->getFile(). That's why you have to implement the upload process manually, on form submission, in your action, without lifecycle callbacks. Like this:

Action:

....
$image = new ImageArticle();

$form = $this->createForm('YOUR_FORM', $image);
$form->handleRequest($request);

if ($form->isValid()) {
    ...

    foreach ($image->getFile() as $uploadedFile) {
        $image = new ImageArticle();
        $image
            // setters go here
        ;

        // Upload process go here

        $image->setFile(null);
    }

    $this->get('doctrine.orm.entity_manager')->flush();

    ....
}

Here is a screenshot from my project:

网友答案:

Something like that ?

public function newArticleAction(Request $request)
{
   $article = new Article();
   $article->setUser($this->getUser());

   $imageArticle = new ImageArticle();

   $form = $this->get('form.factory')->create(new \AD\PlatformBundle\Form\ArticleType(), $article, $image); 
    if($form->handleRequest($request)->isValid())
    {
        foreach($imageArticle->getFile() as $imageArticle)
        {
            $imageArticle = new ImageArticle();

            $imageArticle->setAlt($imageArticle->getAlt());
            $imageArticle->setUrl($imageArticle->getUrl());
            $imageArticle->setFile($imageArticle->getFile());

            $imageArticle->preRemoveUpload();
            $imageArticle->preUpload();
            $imageArticle->upload();

        }
        $em = $this->getDoctrine()->getManager();
        $em->persist($article);
        $em->flush();

        $request->getSession()->getFlashBag()->add('notice', 'Article publi ! :)');
        return $this->redirect($this->generateUrl('va_platform_blog'));
    }
    return $this->render('ADPlatformBundle:Cars:newarticle.html.twig', array(
        'form' =>$form->createView(),
    ));
}
网友答案:

Is your images are save in the article entity or another (I'll make changes when I get your answer) ?

I have made some little changes to your code. I'm not sure about all the code but I think this should work

public function newArticleAction(Request $request)
{
   $article = new Article();
   $images = new ImageArticle();

   $form = $this->get('form.factory')->create(ArticleType::class, $article, $images);
   $form->handleRequest($request);

   if($form->isValid())
   {
       $article->setUser($this->getUser());
       // other article fields, if needed

       foreach($images->getFile() as $image)
       {
           $images->setAlt($image->getAlt());
           $images->setUrl($image->getUrl());
           $images->setFile($image->getFile());

           $images->preRemoveUpload();
           $images->preUpload();
           $images->upload();
       }

       $em = $this->getDoctrine()->getManager();
       $em->persist($article);
       $em->flush();

       $request->getSession()->getFlashBag()->add('notice', 'Article publi ! :)');

       return $this->redirect($this->generateUrl('va_platform_blog'));
    }

    return $this->render('ADPlatformBundle:Cars:newarticle.html.twig', [
        'form' => $form->createView(),
    ]);
}
相关阅读:
Top