Question

I currently use the following code for allowing my users to upload files;

uploadurl = blobstore.create_upload_url('/process?session=' + session, gs_bucket_name='mybucketname')

and I can serve images like this;

imgurl = get_serving_url(blob_key, size=1600, crop=False, secure_url=True)

After content is uploaded using the method in the first code snipped, the blob key contains encoded_gs_file: and that's how it knows to serve it from Google Cloud Service and not the blobstore as standard.

However, I'm unsure how I'd serve any other kind of file (for example .pdf, or .rtf). I do not want the content to be displayed in the browser, but rather sent to the client as a download (so they get the save file dialog and choose a location on their computer to save it).

How would I go about doing this? Thanks.

Was it helpful?

Solution

Using a google serving_url works only for images.

To serve a pdf from the blobstore you can use:

class DynServe(blobstore_handlers.BlobstoreDownloadHandler):

    def get(self, resource):

        (blob_key, extension) = resource.rpartition('.')[::2]
        blob_info = blobstore.BlobInfo.get(blob_key)
        if not blob_info:
            logging.error('Blob NOT FOUND %s' % resource)
            self.abort(404)

        self.response.headers[b'Content-Type'] = mimetypes.guess_type(blob_info.filename)
        self.send_blob(blob_key, save_as=blob_info.filename)

The webapp2 route for this handler looks like:

webapp2.Route(r'/dynserve/<resource:(.*)>', handler=DynServe)

To serve:

<a href="/dynserve/<blob_key>.pdf">PDF download</a>

OTHER TIPS

I'm going to answer my own question based on the answer from @voscausa

This is what my handler looks like (inside a file named view.py);

class DynServe(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, resource):
    blob_key = resource

    if not blobstore.get(blob_key):
        logging.warning('Blob NOT FOUND %s' % resource)
        self.abort(404)
        return
    else:
        blob_info = blobstore.BlobInfo.get(blob_key)

    self.send_blob(blob_key, save_as=blob_info.filename)    

We need this in app.yaml;

- url: /download/.*
script: view.app
secure: always

secure: always is optional, but I always use it while handling user data.

Put this at the bottom of view.py;

app = webapp.WSGIApplication([('/download/([^/]+)?', DynServe),
                                 ], debug=False)

Now visit /download/BLOB_KEY_HERE. (you can check the datastore for your blob key)

That's a fully working example which works with both the standard blob store AND Google Cloud Service.

NOTE: All blob keys which are part of the GCS will start with encoded_gs_file: and the ones which don't are in the standard blobstore; app engine automatically uses this to determine where to locate the file

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top