Downloaded filename with Google App Engine Blobstore
Asked Answered
Q

4

10

I'm using the Google App Engine Blobstore to store a range of file types (PDF, XLS, etc) and am trying to find a mechanism by which the original filename of the uploaded file - as stored in blob_info - can be used to name the downloaded file i.e. so that the user sees 'some_file.pdf' in the save dialogue rather than 'very_long_db_key.pdf'.

I can't see anything in the docs that would allow this:

http://code.google.com/appengine/docs/python/blobstore/overview.html

I've seen hints in other posts that you could use the information in blob_info to set the content-disposition header. Is this the best approach to achieving the desired end?

Quatrain answered 6/9, 2011 at 19:11 Comment(0)
T
12

There is an optional 'save_as' parameter in the send_blob function. By default this is set to False. Setting it to True will cause the file to be treated as an attachment (ie it will trigger a 'Save/Open' download dialog) and the user will see the proper filename.

Example:

class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        self.send_blob(blob_info,save_as=True)

It is also possible to overwrite the filename by passing in a string:

self.send_blob(blob_info,save_as='my_file.txt')

If you want some content (such as pdfs) to open rather than save you could use the content_type to determine the behavior:

blob_info = blobstore.BlobInfo.get(resource)
type = blob_info.content_type
if type == 'application/pdf':       
    self.response.headers['Content-Type'] = type
    self.send_blob(blob_info,save_as=False)
else:
    self.send_blob(blob_info,save_as=True)
Tutto answered 7/9, 2011 at 0:7 Comment(1)
Just to add - if the original filename contains a double quote, the download dialog will truncate the filename after the quote character. I've got around this by escaping double quotes in the blob filename: self.send_blob(blob_info, save_as = blob_info.filename.replace('"', '\\"')) (There's a related discussion about this here)Barbiebarbieri
V
1

For future reference, save_as and the BlobstoreDownloadHandler is documented here:

http://code.google.com/appengine/docs/python/tools/webapp/blobstorehandlers.html

It does seem like it should be a bit easier to find. Let's see if it can be improved.

Volauvent answered 12/9, 2011 at 23:21 Comment(1)
Yes, I did see that once the answer had been pointed out. send_blob seems to be missing from the reference materials too: code.google.com/appengine/docs/python/blobstore/overview.htmlQuatrain
H
1

Another option is to append the file name to the end of the download URL. For example:

/files/AMIfv95HJJY3F75v3lz2EeyvWIvGKxEcDagKtyDSgQSPWiMnE0C2iYTUxLZlFHs2XxnV_j1jdWmmKbSVwBj6lYT0-G_w5wENIdPKDULHqa8Q3E_uyeY1gFu02Iiw9xm523Rxk3LJnqHf9n8209t4sPEHhwVOKdDF2A/prezents-list.doc

If you use Jinja2 for templating, you can construct such an URL like this:

<a href="/files/{{blob_info.key()}}/{{blob_info.filename}}">{{file.filename}}</a>

then you should adapt your URL mapping accordingly to something like this:

('/files/([^/]+)/?.*', DownloadHandler)

If you have the blob key in the URL, you can ignore the file name in your server-side code.

The benefit of this approach is that content types like images or PDF open directly in the browser, which is convenient for quick viewing. Other content types will just be saved to disk.

Huck answered 19/9, 2013 at 11:58 Comment(0)
B
0

Yes it is the best approach; just query the BlobInfo object using the given Blobstore key and use its content-type property.

Bedim answered 6/9, 2011 at 19:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.