上一篇文章我们详细说明了“upload”字段的3个关键属性设置,也明白了web2py的上传文件安全加密重命名机制。
web2py相关的文件加密命名机制保证了数据安全,但标准的用法,只能用一个Form对象,一个一个的上传,如果我们想批量上传文件upload字段文件,且满足web2py原生的文件加密命名机制用怎么操作,假设有表:人员信息,存一张照片,上传的照片文件名就是人员的name:
db.define_table('person',
Field('name','string',label='姓名',writable=False),
Field('photo','upload',label='影像',
uploadfolder=os.path.join(request.folder,'photo'),uploadseparate=True,autodelete=True))
一、解决思路
我们用zip打包文件后,一次上传,解压到临时文件夹后,再用web2py的文件加密命名机制逐行插入;
二、upload字段到底存储了什么
upload字段存的就是web2py上传文件自动加密后的文件名,格式为:
“表名+字段名+UUID+BASE编码加密后的源文件名”
三、开始动手
1、设立一个临时表,用于接收 临时上传的 打包文件
db.define_table('temp_upload', Field('importzipfile','upload',uploadfolder=os.path.join(request.folder,'uploads'),autodelete=True,requires=IS_FILE(extension='zip')))
2、用一个 SQLFORM 对接 temp_upload 表,接收压缩包文件后,解压出来;
3、然后逐个对文件进行插入真正的数据表,先看代码:
def upload(): form_import = SQLFORM(db.temp_upload, fields=['importzipfile'], labels={'importzipfile': 'zip压缩包上传'}, record=None, deletable=False, linkto=None, upload=None, col3={}, submit_button='Submit', keepopts=[], ignore_rw=False, record_id=None, formstyle=None, buttons=[BUTTON('提交上传', _type="submit")], separator=': ', extra_fields=None, _name='form_import') import zipfile import shutil exact_dir = 'photo_temp' if form_import.process(formname='form_import').accepted: try: zipfile = zipfile.ZipFile(os.path.join(request.folder, 'uploads') + '\\' + form_import.vars.importzipfile) except: session.flash = ('发生错误:文件不是有效的zip文件或者已损坏') #因为temp_upload设置了 autodelete=True,删除数据库记录会自动删除上传的文件 db(db.temp_upload.id == form_import.vars.id).delete() redirect(URL(upload)) else: try: zipfile.extractall(path=os.path.join(request.folder, exact_dir)) except : session.flash = ('zip解压错误,检查是否里面有文件损坏') db(db.temp_upload.id == form_import.vars.id).delete() redirect(URL(upload)) else: zipfile.close() db(db.temp_upload.id == form_import.vars.id).delete() #获取解压后的文件列表 files = os.listdir(os.path.join(request.folder, exact_dir)) for file in files: file_path = os.path.join(request.folder, exact_dir) + '\\' + file web2py_filename = uploadfile_restore(file_path,file,"peron","photo") db.person.insert(name=file,photo=web2py_filename) # 整个解压的临时文件夹一起删掉 shutil.rmtree(os.path.join(request.folder, exact_dir)) return locals()
四、uploadfile_restore 函数
我们上面自己编写了一个 uploadfile_restore函数用于文件转储在web2py的文件加密体系,需要4个参数:文件路径、文件名,表名、字段名
def uploadfile_restore(file_path,filename,table_name,field_name): source_file = open(file_path, 'rb') field = db[table_name][field_name] return field.store(source_file,filename,field.uploadfolder)
这里我们使用到了web2py自带的filed类,他完成了上传文件的加密存储,然后返回我们加密后的文件名;