Reputation: 21
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
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