Bitbucket is a code hosting site with unlimited public and private repositories. We're also free for small teams!

Close

REX.ATTACH Programming Guide

Overview

This package provides a file storage for uploaded files.

This package is a part of the RexDB ® platform for medical research data management. RexDB is free software created by Prometheus Research, LLC and is released under the AGPLv3 license with a commensurate attribution clause. For more information, please visit http://rexdb.org/.

The development of this product was supported by the National Institute of Mental Health of the National Institutes of Health under Award Number R43MH099826.

Attachment storage

To start using rex.attach, you need to specify the path to a directory where uploaded files will be stored. The directory must exist and be writable:

>>> import os
>>> if not os.path.exists('./sandbox/attachments'):
...     os.makedirs('./sandbox/attachments')

Use parameter attach_dir to specify the directory:

>>> from rex.core import Rex

>>> demo = Rex('rex.attach_demo', attach_dir='./sandbox/attachments')

Now you can use function get_storage() to get an attachment storage object:

>>> from rex.attach import get_storage

>>> with demo:
...     storage = get_storage()

>>> storage
LocalStorage('./sandbox/attachments')

You can use the storage object to add, access and remove attachments:

>>> handle = storage.add('memo.txt', "Feed the cats!")

The .LocalStorage.add() method returns an opaque handle string, which you could use to retrieve the attachment:

>>> stream = storage.open(handle)
>>> print stream.read()
Feed the cats!

If you know the attachment handle, you can generate an HTTP response containing the attachment:

>>> from webob import Request

>>> req = Request.blank('/download')
>>> app = storage.route(handle)
>>> print req.get_response(app)         # doctest: +ELLIPSIS
200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 14
Content-Disposition: attachment; filename=memo.txt
Last-Modified: ...
Accept-Ranges: bytes
<BLANKLINE>
Feed the cats!

For more information on the attachment storage, please see rex.attach API reference.

File upload and download

rex.attach provides two utility functions to support uploading and downloading attachments.

Function rex.attach.upload takes an uploaded file, adds it to the attachment storage and returns the attachment handle:

>>> from rex.attach import upload

>>> post_req = Request.blank('/upload',
...         POST={'attachment': ('memo.txt', "Feed the cats!")})
>>> attachment = post_req.params['attachment']

>>> with demo:
...     handle = upload(attachment)

Function rex.attach.download takes an attachment handle and produces an HTTP response that contains the attachment:

>>> from rex.attach import download

>>> req = Request.blank('/download')

>>> with demo:
...     print req.get_response(download(handle))    # doctest: +ELLIPSIS
200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 14
Content-Disposition: attachment; filename=memo.txt
Last-Modified: ...
Accept-Ranges: bytes
<BLANKLINE>
Feed the cats!

You can use these functions to implement commands for uploading and downloading files. For example, rex.attach_demo defines a command /upload that takes an uploaded file, adds the file to the attachment storage and saves the attachment handle in the file table. Here is how it looks (with some error handling code removed):

from rex.attach import AttachmentVal, upload

class UploadCmd(Command):

    path = '/upload'
    parameters = [
            Parameter('code', StrVal(r'\w+')),
            Parameter('attachment', AttachmentVal()),
    ]

    def render(self, req, code, attachment):
        handle = upload(attachment)
        db = get_db()
        db.produce('insert(file:={code:=$code, handle:=$handle})',
                   code=code, handle=handle)
        return Response(status=302, location=req.application_url)

rex.attach_demo also defines a command /download to retrieve the attachments. It is implemented as follows:

from rex.attach import download

class DownloadCmd(Command):

    path = '/download'
    parameters = [
            Parameter('code', StrVal(r'\w+')),
    ]

    def render(self, req, code):
        db = get_db()
        handle = db.produce('file[$code].handle', code=code).data
        return download(handle)

Recent activity

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.