简体   繁体   中英

Symfony remove file after download

I am working on a Symfony application where users can crop images with. After someone has downloaded the cropped image I want the application to remove it from the server.

I currently have this controller action:

/**
 * @Route(
 *      "/download/{crop_id}",
 *      name="download_cropped",
 *      options={"expose"=true}
 * )
 *
 * @ParamConverter(
 *      "crop",
 *      class="WebwijsCropperBundle:Crop",
 *      options={"id" = "crop_id"}
 * )
 *
 */
public function downloadAction(Crop $crop)
{
    $dir = $this->container->getParameter('image.cropped.dir');
    return new BinaryFileResponse($dir . '/' . $crop->getCroppedFile());
}

I created this EventListener where I want to remove the image after the response is sent. This Listener will be triggered after every response.

So how do I get the information that I need to know if the response comes from the correct controller action. And how can I get the crop_id parameter so I know which file to remove?

class FileRemovalListener
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function onKernelTerminate(PostResponseEvent $event)
    {
        $response = $event->getResponse();
        $request = $event->getRequest();
        // what do i have to do here to know 
        // from which controller action the response comes?

    }
}

This is the service definition in services.yml

WebwijsCropperBundle\EventListener\FileRemovalListener:
        tags:
            - { name: kernel.event_listener, event: kernel.terminate, method: onKernelTerminate }

If you only want to remove the file, try this:

public function downloadAction(Crop $crop)
{
    $dir = $this->container->getParameter('image.cropped.dir');
    $response = new BinaryFileResponse($dir . '/' . $crop->getCroppedFile());

    $response->deleteFileAfterSend(true);

    return $response;
}

Use

deleteFileAfterSend(bool $shouldDelete)

If this is set to true, the file will be unlinked after the request is sent. Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used.

Just a precision about the function "deleteFileAfterSend(bool $bool)". As symfony documentation said "(...)note that this will not work when the X-Sendfile header is set." . See: https://symfony.com/doc/current/components/http_foundation.html#serving-files . Then you can do something like this for delete a file after response sending:

$zipName = 'downloads/' . uniqid().'.zip';
$response = new StreamedResponse();
$response->headers->set(...);

return $response->setCallBack(function () use($zipName) {
    readfile($zipName);
    $filesystem = new Filesystem();
    try {
       $filesystem->remove($zipName);
    } catch (IOExceptionInterface $exception) {
        echo "Cannot delete the zip file : ". $zipName;
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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