Reputation: 266
HTML:
<form action="/upload" method="post" enctype="multipart/form-data">
Category: <input type="text" name="category" />
Select a file: <input type="file" name="upload" />
<input type="submit" value="Start upload" />
</form>
View:
@route('/upload', method='POST')
def do_login():
category = request.forms.get('category')
upload = request.files.get('upload')
name, ext = os.path.splitext(upload.filename)
if ext not in ('png','jpg','jpeg'):
return 'File extension not allowed.'
save_path = get_save_path_for_category(category)
upload.save(save_path) # appends upload.filename automatically
return 'OK'
I'm trying to do this code but it is not working. What I'm doing wrong?
Upvotes: 23
Views: 27150
Reputation: 353
It is also possible to store files in databases.
Macaron is a common ORM (Object-Relational Mapper) for Bottle and SQLite but has no binary field type. We have to create it until Macaron get one (see here).
from macaron import Field
class BinaryField(Field):
TYPE_NAMES = ("BLOB")
SQL_TYPE = "BLOB"
def __init__(self, max_length=None, min_length=None, length=None, **kw):
super(BinaryField, self).__init__(**kw)
self.max_length, self.min_length = max_length, min_length
self.length = length
if self.length and not self.max_length: self.max_length = self.length
self.type = self.SQL_TYPE
We need to create a model, say Icon :
from macaron import Model, SerialKeyField, CharField,
class Icon (Model):
id = SerialKeyField( primary_key=True )
filename = CharField( max_length=36 )
category = CharField( max_length=36 )
mime = CharField( max_length=36, null=True )
data = BinaryField( )
And then, in the controler, to record the uploaded icon :
import os
import macaron
# [...]
# see bottle and macaron docs
mimes = {
'.png':"image/png",
'.jpeg':"image/jpeg",
'.jpg':"image/jpeg",
}
@route('/upload', method='POST')
@view('icons')
def do_upload():
upload = request.files.get('upload')
name, ext = os.path.splitext(upload.filename)
if upload != None & ext in mimes.keys() :
icon = Icon.create(
filename = upload.filename,
category = request.forms.get('category'),
data = upload.file.read(),
mime = mimes[ext])
macaron.bake()
return dict(
icons = Icon.all()
)
Send the file with :
@route('/icon/<id:int>')
def icon(id):
icon = Icon.get(id)
response.set_header('Content-Type', icon.mime)
return icon.data
Upvotes: 0
Reputation: 856
Starting from bottle-0.12 the FileUpload class was implemented with its upload.save() functionality.
Here is example for the Bottle-0.12:
import os
from bottle import route, request, static_file, run
@route('/')
def root():
return static_file('test.html', root='.')
@route('/upload', method='POST')
def do_upload():
category = request.forms.get('category')
upload = request.files.get('upload')
name, ext = os.path.splitext(upload.filename)
if ext not in ('.png', '.jpg', '.jpeg'):
return "File extension not allowed."
save_path = "/tmp/{category}".format(category=category)
if not os.path.exists(save_path):
os.makedirs(save_path)
file_path = "{path}/{file}".format(path=save_path, file=upload.filename)
upload.save(file_path)
return "File successfully saved to '{0}'.".format(save_path)
if __name__ == '__main__':
run(host='localhost', port=8080)
Note: os.path.splitext() function gives extension in ".<ext>" format, not "<ext>".
If you use version previous to Bottle-0.12, change:
...
upload.save(file_path)
...
to:
...
with open(file_path, 'wb') as open_file:
open_file.write(upload.file.read())
...
Upvotes: 40