Akriti
Akriti

Reputation: 21

File uploading in web2py

I want to make an option for uploading a file in my web2py app.Below is my code but the problem is whenever i am refreshing the page,an empty copy file is being created and is displayed for download.How can i solve this problem.please help!!

model:

db.define_table('image',
Field('title'),
Field('file', 'upload'),
format = '%(title)s')

controller:

def download(): return response.download(request,db)
def link(): return response.download(request,db,attachment=False)

def index():

image_form = FORM(
    INPUT(_name='image_title',_type='text'),
    INPUT(_name='image_file',_type='file')
    )

if image_form.accepts(request.vars,formname='image_form'):

    image = db.image.file.store(image_form.vars.image_file.file,image_form.vars.image_file.filename)
    id = db.image.insert(file=image,title=image_form.vars.image_title)

images = db().select(db.image.ALL)

return dict(images=images)

view:

 {{extend "layout.html"}}

 <form action="" enctype="multipart/form-data" method="post">
  <input name="_formname" type="hidden" value="image_form">
<input class="string" name="image_title" type="text" value="">
<input class="upload" name="image_file" type="file">
<input type="submit" value="Submit">
 </form>

   <ul>
  {{for image in images:}}
    <li>
    <a href="{{=URL(f='link', args=image.file)}}">
        <img src="{{=URL(f='link', args=image.file)}}"/>
        {{=image.title}}
    </a>
    <a href="{{=URL(f='download', args=image.file)}}">
        [Download]
    </a>
</li>
 {{pass}}
 </ul>

Upvotes: 1

Views: 6425

Answers (1)

Anthony
Anthony

Reputation: 25536

You shouldn't refresh a page that was requested via POST, as the browser will re-submit the data (that's why the browser shows a warning).

If you change your form code to:

image_form.accepts(request.vars, session, formname='image_form')

web2py will automatically create a "_formkey" token for the form (to prevent double submission as well as to protect against CSRF attacks). To take advantage of that, you will also have to include the "_formkey" and "_formname" hidden fields in the form, which you can do by including the following in the form HTML:

{{=image_form.hidden_fields()}}

Note, your controller function will need to return the image_form object so it will be available in the view. With this approach, if the form is re-submitted, it won't validate because the _formkey token will no longer be valid.

Another option is to do a redirect after successful form submission -- this will automatically reload the page in the browser via a GET request, so a subsequent refresh will not trigger a re-submission:

if image_form.accepts(request.vars, session, formname='image_form'):
    image = db.image.file.store(image_form.vars.image_file.file,
                                image_form.vars.image_file.filename)
    id = db.image.insert(file=image,title=image_form.vars.image_title)
    redirect(URL('default', 'index'))

Upvotes: 2

Related Questions