- 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, requires=[IS_NOT_EMPTY(), IS_LENGTH(1048576, 1024, error_message=CustomMessages.UPLOAD_CV_SIZE) ] ), INPUT(_type='submit')) if form.accepts(request.vars, formname=formname): stream=eval('form.vars.%s.file'%formname) filename= eval('form.vars.%s.filename'%formname) file_id = db.cvs.insert(cv=db.cvs.cv.store(stream,filename=filename), job_title=job.title, job_id=job.id) # add permissions for that file # do other stuff
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 .
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:
stream=form.vars.field_name.file filename= form.vars.field_name.filename
Now you can store your file name into the database
db.cvs.insert(cv=db.cvs.cv.store(stream,filename=filename), job_title=job.title, job_id=job.id)
see the :
db.table_name.field_of_type_upload.store()
Congratulations !!! you’ve uploaded your files
def download_cv(): file_id = request.args(0) import cStringIO import contenttype as c s=cStringIO.StringIO() (filename,file) = db.cvs.cv.retrieve(db.cvs[file_id].cv) s.write(file.read()) 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,\ c='files', f='download_cv', args=[row.id] )) for row in cvs] return urls
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 ?
What is difference between them?
response.download() calls response.stream() to do the streaming stuff.
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(): filename=request.args[0] path=os.path.join(request.folder,'uploads',filename) response.headers['ContentType'] ="application/octet-stream"; response.headers['Content-Disposition']="attachment; filename=" +filename return response.stream(open(filename),chunk_size=4096)