How to download a variable number of files with one multi-page post header
I have a repeating form field:
<div class="repeat">
<input type="file" name="files[==row-count-placeholder==]" />
</div>
which will (using jQuery) for example will result in
<div class="repeat">
<input type="file" name="files[0]" />
<input type="file" name="files[1]" />
<input type="file" name="files[2]" />
<!-- and so on -->
</div>
depending on how many files the user needs to download. Forms method post
and enctype is multipart/form-data
.
Using cherrypy as my server and voluptuous validation library, I would like to keep the uploaded files:
import voluptuous
def save_uploaded_file(file, path)
#save file on server...
def validate_files(files):
for file in files:
save_uploaded_file(file, cherrypy.request.config['static_dir'])
@cherrypy.expose
def index(self, **kwargs):
schema = Schema({
'files' : validate_files
}, required = True, extra = True)
kwargs = schema(kwargs)
So I really need a message header containing information about all the files (something like a list of files would be best) under one key called files
, but all I get is a few keys like files[0]
, files[1]
etc.
How do I approach this? Should I somehow manually create an array containing all the information files
, or is there a more general or practical way to do this?
Solution (following suggestion by saaj):
schema_dict = {
'name' : All(Length(min=3, msg="Can't believe that there is a name less than 3 characters...")),
# ...
}
# validate files
isPart = lambda v: isinstance(v, cherrypy._cpreqbody.Part)
files1 = [a for a in kwargs.values() if isPart(a)]
files2 = [a for a in cherrypy.request.params.values() if isPart(a)]
assert files1 == files2
for file in files1:
# for each file add dict entry and route to validation function
schema_dict.update({file.name : validate_file})
schema = volu.Schema(schema_dict, required = True, extra = True)
Likewise it Schema
can contain many other fields. The presented files are generally added to any Schema
. Cool!
source to share
Just take the files from the request (if your form doesn't contain other types of parts, you can take the request parameters as they are).
@cherrypy.expose
def index(self, **kwargs):
isPart = lambda v: isinstance(v, cherrypy._cpreqbody.Part)
files1 = [a for a in kwargs.values() if isPart(a)]
files2 = [a for a in cherrypy.request.params.values() if isPart(a)]
assert files1 == files2
print(files1) # pass it where you want to
CherryPy related questions: load performance , asynchronous loading .
source to share