1

I've been exploring the issue of allowing web site visitors to securely upload images. I've come across this article: Long article about securly uploading images

It seems that the most important thing is to store the files outside of the document root.

Now, if i understand correctly, the "document root", in the case of using XAMPP, for instance, is what $_SERVER["DOCUMENT_ROOT"] gives, which is C:/xampp/htdocs in my case. So putting my upload directory "outside" of it would mean creating a directory in C:/xampp. Am i right?

Anyway, I've tried doing so, and couldn't load the images in the template. The image source would always be interpreted as having "http://localhost..." in the beginning, and therefore the file can't be found.

I saw on that article that a function called readfile() needs to be used, but i have no clue how to implement it on Twig.

I would appreciate any help resolving this issue.

i.brod
  • 3,993
  • 11
  • 38
  • 74

2 Answers2

2

The public directory of Symfony is your_project/web so you don't want to upload private files there. Instead you can upload them to a specific private folder.

Example below lets you upload files to your_project/Resources/private/uploads/images folder and serve them in twig. When it comes to serving the images, it is a bit different to classic way. You create a route to return you image as BinaryFileResponse then show it in your twig.

I am posting just the critical parts here but you can see the full example here: Uploading images to a private directory and serving them in twig template

Note: You can always change the way how route below works. For example, name parameter could be a hash etc.

Controller action that servers image. Twig calls this.

/**
 * @param string $name
 *
 * @Method({"GET"})
 * @Route("/{name}", name="image_show")
 *
 * @return Response
 */
public function showAction($name)
{
    $response = new BinaryFileResponse($this->imageUploadPath.'/'.$name);
    $response->trustXSendfileTypeHeader();
    $response->setContentDisposition(
        ResponseHeaderBag::DISPOSITION_INLINE,
        $name,
        iconv('UTF-8', 'ASCII//TRANSLIT', $name)
    );

    return $response;
}

This is the Twig part which displays image(s). The images variable comes from indexAction() which you can see in the full example. The important part is this: {{ path('image_show', {'name': image}) }}. It calls action above.

{% for image in images %}
    <img src="{{ path('image_show', {'name': image}) }}" />
{% else %}
    <em>No image found.</em>
{% endfor %}
BentCoder
  • 12,257
  • 22
  • 93
  • 165
  • Thank you for the elaborate reply! I need to mention i ain't using symphony framework, but rather a custom-made mini framework, that uses twig as templating engine :-) – i.brod Sep 24 '17 at 07:30
  • Remove symfony tag from your question please. – BentCoder Sep 24 '17 at 09:12
0

Twig is a templating language to generate html. What you want to do, cannot be done there. You will need to use twig to generate your html as you always do.

However, when you add an image tag, you need to set the source to a php script that gets the image from the file-system and returns it's source in combination with the correct image header.

So twig needs to generate the html with a small change in the image source, but you need a separate php script to serve the image based on the conditions you have (GET parameters, session information, etc.).

You could of course send the encoded image source directly to the source of the image tag in twig, but that is not really practical for larger images as the size of your html source will explode.

jeroen
  • 91,079
  • 21
  • 114
  • 132