2

Via an XML import I'm getting also an url link to jpg images on an external server. I want to copy the images. I'm tried to do this via UploadedFile() function in Symfony to then add them in my entity.

Via the following code I want to add the url image in the Symfony image object.

$f = new UploadedFile();
$f->openFile($imageUrl);

So after opening the file I want to add them in my image entity.

$image = new image();
$image->setFile($f);

This entity contains the following file parameters:

/**
* Sets file.
*
* @param \Symfony\Component\HttpFoundation\File\UploadedFile $file
*/
public function setFile(UploadedFile $file = NULL) {
    $this->file = $file;
}

/**
* Get file.
*
* @return UploadedFile
*/
public function getFile() {
    return $this->file;
}

Then I get the error that arguments are missing. But with an from it works with the following code:

$image = new image();
$image->setFile($request->files->get('images'));
2
  • What i understand is you get an image url from a xml file and you want to upload the image on your server ? Commented Nov 6, 2016 at 23:21
  • Yes correct, I want to put it in the Symfony File object so I can process it the same way as the uploaded images in the form. Commented Nov 7, 2016 at 5:42

3 Answers 3

6

I use vich uploader bundle (https://github.com/dustin10/VichUploaderBundle) to uploads images, the bundle provides a way to upload images from forms. I had the same use case than you. I have to import images from a xml.

I use vich service (vich_uploader.upload_handler) to do that from a xml:

Entity:

namespace AppBundle;

use Doctrine\ORM\Mapping AS ORM;
use Symfony\Component\HttpFoundation\File\File;

/**

 * @ORM\Table(name="entity")
 * @Vich\Uploadable
 */
class Entity
{

/**
 * @ORM\Column(type="string", nullable=true)
 */
private $image;

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


/**
 * @return File
 */
public function getImageFile()
{
    return $this->imageFile;
}

/**
 * @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');
    }
}
}

service:

<?php

namespace AppBundle;

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Handler\UploadHandler;

class ExternalImageUploader
{

private $uploadHandler;
private $kernelRootDir;


public function __construct(UploadHandler $uploadHandler, $kernelRootDir)
{
    $this->uploadHandler = $uploadHandler;
    $this->kernelRootDir = $kernelRootDir;
}

public function copyExternalFile($url, $entity)
{

    $newfile = $this->kernelRootDir.'/../web/uploads/test.jpg';

    copy($url, $newfile);
    $mimeType = mime_content_type($newfile);
    $size = filesize ($newfile);
    $finalName = md5(uniqid(rand(), true)).".jpg";

    $uploadedFile = new UploadedFile($newfile,$finalName,$mimeType, $size);

    $entity->setImageFile($uploadedFile);
    $this->uploadHandler->upload($entity,'imageFile');


}
}

services.xml

<service id="app.external_image_uploader" class="AppBundle\ExternalImageUploader">
        <argument type="service" id="vich_uploader.upload_handler" />
        <argument>%kernel.root_dir%</argument>
    </service>
Sign up to request clarification or add additional context in comments.

3 Comments

Where do you call the private function copyExternalFile?
I have edit the private method to public. It should be called from your controller or other service
Note here that the key to making this work is the final true when creating the UploadedFile, this is a "test" mode which makes it ignore all of the upload validation logic. Since the test mode is there for the unit tests, I'm not sure how stable this will be in the future.
1

To download a file from a url with php you will need to take a look at : http://php.net/manual/fr/function.file-get-contents.php

With Symfony File object, To persist an Image if you have an image entity :

namespace AppBundle\Entity;

use Symfony\Component\HttpFoundation\File\File;

class Image
{
    protected $file;

    public function setFile(File $myFile = null)
    {
        $this->file = $myFile;
    }

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

if you want to specify some validation rules using annotations

use Symfony\Component\Validator\Constraints as Assert;

class Image
{
    /**
     * @Assert\File(
     *     maxSize = "1024k",
     *     mimeTypes = {"image/jpeg", "image/png"},
     *     mimeTypesMessage = "Please upload a valid image"
     * )
     */
    protected file;
}

Then the upload function that move the file

public function upload(File $file)
{
    //generate unique filename
    $fileName = md5(uniqid()).'.'.$file->guessExtension();
 
    //Set other entity attribute here

    //move the file
    $file->move($targetDirectory, $fileName);

    return $fileName;
}

And then in controller do something like this

$em = $this->getDoctrine()->getManager();
$image = new Image();
$file = file_get_contents('http://www.example.com/');
$image->setFile($file);
$image->upload();
//Maybe persist your entity if you need it
$em->persist($image);
$em->flush();

This is a quick example to help you, might not work with copy past (and it's not the purpose).

Take a look at : http://symfony.com/doc/current/controller/upload_file.html

4 Comments

I have edited my question so it is more clear on what i'm looking for.
I don't know if i understand your question more than before. From what i understand you want to save an image from an url which correspond to my previous answer.
Thanks Thomas for answering. I have a lot extra function made in the entity like generate unique name, store the image in specific loaction, guess filetype enzo.. I like to reuse these functions, but these are based on an Symfony file object. I just having troubles getting the image as an url in the object as with the upload form it works fine.
In api.symfony.com/2.3/Symfony/Component/HttpFoundation/File/… i don't see any reference to openFile method you are trying to use. Try to use only what i put in my last code example and replace your getter and setter also t use File class
-1

Update based on @h3llr4iser answer:

<?php

namespace App\Services;

use App\Entity\MyEntity;
use Vich\UploaderBundle\FileAbstraction\ReplacingFile;
use Vich\UploaderBundle\Handler\UploadHandler;

final class ExternalImageUploader
{
    public function __construct(private UploadHandler $uploadHandler)
    {
    }

    public function copyExternalFile(string $url, MyEntity $entity)
    {
        $newfile = tempnam(sys_get_temp_dir(), 'prefix_');
        copy($url, $newfile);
        $uploadedFile = new ReplacingFile($newfile);

        $entity->setImageFile($uploadedFile);
        $this->uploadHandler->upload($entity,'imageFile');
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.