Upload Download files

  • Using multiple tables in the same page as you know requires explicitly adding form name when you accept it
  • suppose a situation in which you need to make multiple upload forms in the same page may be for users to upload their cvs
  • Now you’ve 3 problems :
    • How could you add multiple forms in the same page and in the same time make them work ?
    • How to upload the files (cvs)
    • How to download them
    def jobs():
            jobs = db(...).select(...)
            for job in jobs:
                # I'll use the same name for form name as well as the field
                formname = "upload_f_%s"%job.id
                form = FORM(INPUT(_type="file",_name=formname,
                                        IS_LENGTH(1048576, 1024, error_message=CustomMessages.UPLOAD_CV_SIZE)
                if form.accepts(request.vars, formname=formname):
                    filename= eval('form.vars.%s.filename'%formname)        
                    file_id = db.cvs.insert(cv=db.cvs.cv.store(stream,filename=filename),
                    # add permissions for that file    
                    # do other stuff       
  • As you see , I made a form with a field of type ‘file’ and form name is variable based on the job_id , C.Vs are going to be uploaded
    this helps making multiple forms per page and in the same time every form has a unique name that will be used when accepting the form .
  • Now as you may have guessed the form containing a ‘file’ field will have (when being accepted) :
    form.vars.field_name.file  -> get the reference to the file
    form.vars.field_name.filename  -> get the file name

    Now you can easily do something like:

    filename= form.vars.field_name.filename

    Now you can store your file name into the database


    see the :

  • Congratulations !!! you’ve uploaded your files

  • Now for downloading files you can do :
    def download_cv():
        file_id = request.args(0)
        import cStringIO 
        import contenttype as c
        (filename,file) = db.cvs.cv.retrieve(db.cvs[file_id].cv)
        response.headers['Content-Type'] = c.contenttype(filename)
        response.headers['Content-Disposition'] = \
                    "attachment; filename=%s" % filename  
        return s.getvalue()

    Now you can make another function that list all cvs available with a link for downloading them as follows:

    def list_Cvs():
        cvs = db(db.cvs.id>0).select(db.cvs.cv) # db.cvs.cv is of type 'upload'
        urls = [A('Download', _href=URL(r=request,\
                                                   f='download_cv', args=[row.id]
                     )) for row in cvs]
        return urls
  • what is the benefit of writing my own download function ?
    This enables you to write your own authorization logic before allowing a user to download a file

  • Now what if I just don’t want to write my own download function and use web2py facilities for that matter ?

  • You can use response.stream(), or response.download() functions.
  • What is difference between them?

  • In fact response.stream is the main download function that takes care of streaming files.
    response.download() calls response.stream() to do the streaming stuff.
  • response.download() has its arguments as request, db and is used for downloading files by their names, while the name is the name of the file in the database.
                def download():
                    return response.download(request, db)
            #downloads from http://..../download/filename

    response.download() takes request to extract from it the file name stored in [request.args]

    download function is mainly used by SQLFORM to update a record that includes an upload field that is used to upload an image, in this case response.download() gets the file (image) to be displayed when updating this record.

    form = SQLFORM(db.my_table, record, upload=URL(r=request, c='default', f='download'))
  • Suppose you want to stream an MP3 file, you can do something like:

    Somebody asked how to stream an mp3 file from the uploads files directly:
    def get_my_file():
          response.headers['ContentType'] ="application/octet-stream";
          response.headers['Content-Disposition']="attachment; filename="  
          return response.stream(open(filename),chunk_size=4096)

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out /  Change )

    Google photo

    You are commenting using your Google account. Log Out /  Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out /  Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out /  Change )

    Connecting to %s

    %d bloggers like this: