Search code examples
phpsymfonyfile-uploadsymfony3.x

Replace file uploaded on edit?: Symfony3


I have implemented a file upload with an Entity, following the Symfony 3 docs. My trouble arises from attempting to edit the entity once it is saved. I have done as the docs note and created a new File() instance using the file name stored in the DB and the path set as a parameter prior to rendering the edit form.

My trouble arises when I attempt to submit the edit form. I end up with a FileNotFoundException for the previously uploaded file. It seems that setting the entity's file attribute to the new File() instance is resulting in the path and md5'd file name being shoved into the DB. I haven't been able to find a comprehensive example for editing an entity with an uploaded file attached.

Is what I am seeing in the DB (the path to the file + the file name being inserted into the DB field for the name of the file) what should be happening? Can anyone spot the issue with my code that would result in the error I've described? Can anyone give me a the general process for replacing an uploaded file on edit of the entity to which it belongs? Controller:

public function addItemAction(Request $request, Category $category){
  $directory = $this->setDirectory($category);

  if($this->ensureDirectorySize($directory)){
    $item = new Item();

    $form = $this->createForm(ItemType::class, $item);
    $form->handleRequest($request);

    if($form->isSubmitted() && $form->isValid()){
      $this->handleUpload($item, $directory, $category);

      return $this->redirect($this- >generateUrl('category_show', array('id' => $category->getId(), '')));
     }
   }else{
     $this->get('session')->getFlashBag()->add('alert', "Sorry, this category is full. No items may be added until some are removed.");
     return $this->redirect($this->generateUrl('category_show', array('id' => $category->getId(), '')));
   }

   return $this->render('Admin:add-item.html.twig', array(
        'form' => $form->createView()
    ));
}

public function editAction(Request $request, Item $item){
    $category = $item->getCategory();
    $item->setFile(new File($this->getParameter('items_directory').$category->getParent()->getId().'/'.$category->getId().'/'.$item->getFile()));


    $form = $this->createForm(ItemType::class, $item);
    $form->handleRequest($request);
    $itemDir = $this->getParameter('items_directory').$category->getParent()->getId().'/'.$category->getId();

    if($form->isSubmitted() && $form->isValid()){
        $this->handleUpload($item, $itemDir, $category);

        return $this->redirect($this->generateUrl('category_show', array('id' => $category->getId(), '')));
    }
    return $this->render('Admin:edit-item.html.twig', array(
        'form' => $form->createView(), 'item'=>$item
    ));
}

private function handleUpload($item, $directory, $category){
    /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file */
    $file = $item->getFile();
    $ext = $file->guessExtension();
    $fileName = $this->generateUniqueFileName().'.'.$ext;

    $file->move($directory,$fileName);

    $item->setFile($fileName);
    $item->setUploadedAt(new \DateTime());
    $item->setCategory($category);
    $item->setType($ext);
    $item->setOriginalFileName($file->getClientOriginalName());

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

Solution

  • My issue was that I had a subrequest which was flushing the setFile() call. Making an entry in the sessionLog such that the particular subrequest no longer flushed the entity manager solved the issue.