Allan Ruin
Allan Ruin

Reputation: 5277

How to delete generated zip file after user finish download?

I'm developing a website using beego

I'm having a zip file generated to let user download from my website. However,I don't know when to delete the file. Is there a way for me to know if user have finished download the zip file, so I could delete it from disk?

Or, Can I generate zip file on-the-fly and past the *zip.File to net/http? I see http.ServeFile() accept a ReadSeeker, yet I think zip.File don't satisfy ReadSeeker interface according to the doc.

Is there a good way to do file delete on my situation?

Upvotes: 3

Views: 5189

Answers (3)

infiniteLearner
infiniteLearner

Reputation: 4189

Like @Paul Hankin suggested , I am just adding code.

return middleware.ResponderFunc(func(w http.ResponseWriter, r runtime.Producer) {
        fn := filepath.Base(filePath)
        w.Header().Set("Content-Type", "application/octet-stream")
        w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", fn))
        io.Copy(w, file)
        defer os.Remove(filePath) // Path to file you've downloaded.
        file.Close()
    })

Upvotes: 2

Paul Hankin
Paul Hankin

Reputation: 58231

You need to defer os.Remove(zf) somewhere in your request handler. A user downloading a file is no different from any other request: you know you're done when the request handler has finished executing.

This will still leave the occasional zip file on disk (for example, if your server crashes, restarts, or is otherwise interrupted), so you'll need a cron job or similar to run periodically to remove old files.

It's possible to generate a zipfile on the fly, using http.ServeContent, if you can regenerate the zipfile consistently (which will require, for example, that your underlying data is either unchanging or versioned). You can do this by writing your own Seek on top of zip that always resets the zip stream and skips ahead n bytes. This would be horrendously inefficient if there was a lot of seeking, but you can refuse to accept ranges and then there'll be exactly two seeks: one to the end of the file and one back to the start (done to compute the length).

Another simple way to avoid disk files is to generate the zip file in memory, and then use a strings.Reader to serve it via http.ServeContent. It'll be hard to manage memory use in your server with this solution though.

Upvotes: 2

ymg
ymg

Reputation: 1500

Import "os" and run the following line:

os.Remove(filename)

Edit: The only way I could see this happening is by using an ajax library to download the files from an api then call a different api on finish. Normal ajax calls wont work here as all browsers wont allow ajax to access the disk directly, so the only way to do this is by using a library like this one http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/

The library api can leverage things like success and failure callbacks in the following way:

$.fileDownload('/url/to/download.pdf', {
    successCallback: function (url) {

        //do another ajax call to delete the file...
    },
    failCallback: function (html, url) {
        //handle failure...
    }
}); 

Upvotes: 2

Related Questions