Sqlform and uploads

Fields of type "upload" are special. They are rendered as INPUT fields of type="file". Unless otherwise specified, the uploaded file is streamed in using a buffer, and stored under the "uploads" folder of the application using a new safe name, assigned automatically. The name of this file is then saved into the field of type uploads.

As an example, consider the following model:

1 db.define_table('person',

You can use the same controller action " display_form" shown above. When you insert a new record, the form allows you to browse for a file. Choose, for example, a jpg image. The file is uploaded and stored as:

1 applications/test/uploads/person.image.XXXXX.jpg

"XXXXXX" is a random identifier for the file assigned by web2py.

Notice that, by default, the original filename of an uploaded file is b16encoded and used to build the new name for the file. This name is retrieved by the default "download" action and used to set the content disposition header to the original filename.

Only its extension is preserved. This is a security requirement since the filename may contain special characters that could allow a visitor to perform directory traversal attacks or other malicious operations.

The new filename is also stored in form. vars . image_newf ilename.

When editing the record using an UPDATE form, it would be nice to display a link to the existing uploaded file, and web2py provides a way to do it.

If you pass a URL to the SQLFORM constructor via the upload argument, web2py uses the action at that URL to download the file. Consider the following actions:

1 def display_form():

2 if len(request.args):

3 records = db(db.person.id==request.args[0]).select()

4 if len(request.args) and len(records):

6 form = SQLFORM(db.person, records[0], deletable=True, upload=

url)

7 else:

8 form = SQLFORM(db.person)

9 if form.accepts(request.vars, session):

10 response .flash = 'form accepted'

11 elif form.errors:

12 response.flash = 'form has errors'

13 return dict(form=form)

16 return response .download(request, db)

Now, insert a new record at the URL:

1 http://127.0.0.1:8000/test/default/display_form

Upload an image, submit the form, and then edit the newly created record by visiting:

1 http://127.0.0.1:8000/test/default/display_form/3

(here we assume the latest record has id=3). The form looks like the following:

Grid Sqlform Grid Web2py

This form, when serialized, generates the following HTML:

1 <td><label id= "person_image_label" for="person_image">Image: </label

></td><td><div><input type="file" id= "person_image" class="upload " name="image" />[<a href="/test/default/download/person.image .0246683463831.jpg">file</a>|<input type="checkbox" name="

image_delete" />delete]</div></td><td></td></tr><tr id="

delete_record_row"><td><label id="delete_record_label" for="

delete_record">Check to delete:</label></td><td><input type= " checkbox" id="delete_record" class= "delete" name=" delete_this_record" /></td>

This form, when serialized, generates the following HTML:

1 <td><label id= "person_image_label" for="person_image">Image: </label

></td><td><div><input type="file" id= "person_image" class="upload " name="image" />[<a href="/test/default/download/person.image .0246683463831.jpg">file</a>|<input type="checkbox" name="

image_delete" />delete]</div></td><td></td></tr><tr id="

delete_record_row"><td><label id="delete_record_label" for="

delete_record">Check to delete:</label></td><td><input type= " checkbox" id="delete_record" class= "delete" name=" delete_this_record" /></td>

which contains a link to allow downloading of the uploaded file, and a checkbox to remove the file from the database record, thus storing NULL in the "image" field.

Why is this mechanism exposed? Why do you need to write the download function? Because you may want to enforce some authorization mechanism in the download function. See Chapter 8 for an example.

Was this article helpful?

+1 0

Responses

  • cara
    How to install SQLForm from web2py?
    8 years ago

Post a comment