Friday, October 25, 2013

Re: File clean up after using CakeResponse::file()

Hey Reuben

Out of sheer curiosity (once again *g*), I gave it a try.

You are right, there is no way to do this in one request/response since sending the response is the last thing the browser does. That's just how HTTP works.

There are two ways though, I think (and I'm may be wrong, it 7 in the morning...):
1. Never save the file to the disk, serve it directly from the memory. Probably not applicable due to file size.
2. A trick that could work is after sending the content to the browser, send a redirect afterwards.

I could verfiy that the content gets send and the browser (Firefox at least) redirects me the the new location:

public function download() {
        $path = WEBROOT_DIR . DS . 'files' . DS . 'testfile1.txt';
        $file = new File($path, true, 0644);
        $created = $file->create();
        $opened = $file->open($path);
        $data = str_pad('', 102400, '1234567890');
        $written = $file->write($data);
        $closed = $file->close();

        $this->response->file($path, array('download' => true);
        $this->response->header('Location', Router::url(array('action' => 'delete_file', 'testfile1.txt')));
    }

The action that the user get's redirected to has to delete the file and may be redirect the user again to another page.
I didn't test it thourougly though.
A problem could be, if the file is big, that the webserver is still sending the file.
But either that is an edge case or you could wait for the file to get released and then delete it, I don't know what works for you.

This could be totally bullshit, because I've actually haven't worked with CakeResponse yet...
Anyway, I'd love to hear what worked for you in the end.

Greeting from Switzerland
Marc

On Friday, October 25, 2013 8:36:36 AM UTC+2, Reuben wrote:
Just had a thought.  A really short cache could also do the trick, as long as that cache content could be referenced by CakeResponse::file().

On Friday, 25 October 2013 16:34:39 UTC+10, Reuben wrote:
Looking at the way CakeResponse::file() works, it does not appear it is possible to clean up a particular file in the same request that generated it, because the file is send when the body is actually generated, which is after afterFilter, and after all the Dispatch Filters would have fired.

Instead, I opted for a method where the method that downloads a file also cleans up temporary files that may be more than 5 minutes old.  The files that are getting downloaded are not that big, and the connections to the website are not expected to be slow, so there shouldn't be an issue of unlinking files that are in the middle of downloading.  And if it does take more than 5 minutes to download, bad luck.

Regards
Reuben Helms

On Friday, 25 October 2013 14:14:15 UTC+10, Reuben wrote:
I have a function that extracts a file from an archive, and streams it to the client via CakeResponse::file().

As a part of extracting the file from the archive, I've had to put it in a temporary file, and then pass that to CakeResponse::file().

Once this is done, I'd like to clean up the temporary file, however, I'm having trouble finding a good place to do it.

Currently, I'm setting a property on the controller so that I can work out what file I have to remove later.

I've tried using afterFilter on the controller, but this seems to remove the file before it starts getting streamed to the user.

The next spot might be in a Dispatch filter, but I've got no idea where to start, and if a dispatch filter has access to the controller.

Any pointers, please?

Regards
Reuben Helms

--
Like Us on FaceBook https://www.facebook.com/CakePHP
Find us on Twitter http://twitter.com/CakePHP
 
---
You received this message because you are subscribed to the Google Groups "CakePHP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cake-php+unsubscribe@googlegroups.com.
To post to this group, send email to cake-php@googlegroups.com.
Visit this group at http://groups.google.com/group/cake-php.
For more options, visit https://groups.google.com/groups/opt_out.

No comments: