def save_image(self, user_id, user_category, file_save): """ 保存富文本编辑器上传的图片: 图片要压缩, 图片转为jpeg格式 :param user_id: 图片使用者的id :param user_category: 图片使用者的分类信息,通过分类信息dict,可以获取很多有用信息 :param file_save: 要保存的文件 :return: 图片保存的路径(含静态路径) """ try: # 获取文件 filename = os.path.splitext( file_save['filename'])[0] # 只有上传文件对应的part才有该键,通过抛出异常来获得有效文件 # 文件类型 file_type_full = file_save['content_type'] # u'image/jpeg' if '/' in file_type_full: # image file_type = file_type_full.split('/')[0] elif '\\' in file_type_full['type']: file_type = file_type_full['type'].split('\\')[0] elif '\\\\' in file_type_full['type']: file_type = file_type_full['type'].split('\\\\')[0] else: file_type = 'unknown' # 生成文件名 name_use = self.make_file_name_with_user_id( user_category=user_category['category'], user_id=user_id, file_category='u', file_suffix='.jpg') # 文件夹相对路径: files/upload/2017/3/24 path_folder_relative_no_static = self.make_path_folder_relative_no_static( ) # 文件夹绝对对路径:..../static/files/upload/2017/3/24 path_folder_absolute = PathUtils.connect( path.PATH_STATIC, path_folder_relative_no_static) # 文件保存绝对路径 path_save_use = PathUtils.connect(path_folder_absolute, name_use) # 数据库路径 path_db_use = PathUtils.to_url( PathUtils.connect(path_folder_relative_no_static, name_use)) # 创建保存路径 if not os.path.exists(path_folder_absolute): os.makedirs(path_folder_absolute) # 从字符串生成图片, 并保存为jpg(保存路径后缀决定) Image.open(StringIO.StringIO(file_save['body'])).save( path_save_use, format='jpeg') # 如果原始文件大小超标,压缩 if os.path.getsize( path_save_use) > user_category['image_size_limit']: self.compress_image(image_file_path=path_save_use, category_info=user_category) file_size = os.path.getsize(path_save_use) image_id = TimeUtils.time_id() date_time = TimeUtils.datetime_date_simple() param_origin = { 'id': image_id, 'user_id': user_id, 'user_category': user_category['category'], 'file_category': 'use', 'title': name_use, 'summary': filename, 'type': file_type, 'created': date_time, 'size': file_size, 'path': path_db_use } self.insert_one_item(user_category['file_table'], **param_origin) # 返回数据 return self.add_static(path_db_use) except Exception as e: traceback.print_exc() app_log.error(e) return ''
PATH_STATIC = os.path.join(PATH_BASE, NAME_STATIC) # 模板路径 PATH_TEMPLATE = os.path.join(PATH_BASE, NAME_TEMPLATE) # 以下路径都是不含静态文件夹名的相对路径 # 默认使用文件路径保存的路径(files/default/)(该文件夹下放:默认logo、默认缩略图、验证码图片) PATH_DEFAULT_FILE = os.path.join(NAME_FILE_ROOT, 'default') # 上传文件的路径(files/upload/) PATH_UPLOAD = os.path.join(NAME_FILE_ROOT, 'upload') # 这样写系统相关,使用时要通过os.path.join转为系统无关 # 临时文件存放夹(该文件夹可随意删)(files/temp/) # PATH_TEMP = os.path.join(NAME_FILE_ROOT, 'temp') PATH_TEMP = os.path.join(PATH_STATIC, NAME_FILE_ROOT, 'temp') # 上传的 logo 保存的路径(保存在 upload 文件夹下) PATH_LOGO = 'logo' # 默认缩略图路径(不含静态文件夹名,url 形式) PATH_THUMB_DEFAULT = 'files/default/default_thumb.jpg' # 默认logo文件的路径(数据库没有内容时用) PATH_LOGO_DEFAULT = 'files/default/logo.png' # 验证码存放相对路径 PATH_VERIFY_SAVE_RELATIVE = PathUtils.connect(PATH_STATIC, 'files/default') # 验证码存放绝对路径 PATH_VERIFY_SAVE_ABSOLUTE = PathUtils.connect(PATH_STATIC, 'files/default/verify.jpg') # 验证码网页使用路径 PATH_VERIFY_URL = StringUtils.connect('/', NAME_STATIC, '/', 'files/default/verify.jpg') # 验证码字体文件路径 PATH_VERIFY_FONT = PathUtils.connect(PATH_STATIC, 'files/default/Monaco.ttf')
def save_upload_file(self, post_streamer, user_id, user_category_info, file_title): """ 返回文件路径、文件 id :param post_streamer: :param user_id: 文件使用者id :param user_category_info: 文件使用者的分类 :param file_title: 文件名称 :return: """ def clean_file_name(file_name): """ 去除文件名中不规范的项目(利用正则表达式) """ re_str = r"[\/\\\:\*\?\"\<\>\| _]" # '/\:*?"<>|' return re.sub(re_str, "", file_name) # 获取文件信息 file_info = {} for part in post_streamer.parts: """ [ { headers:[ {params, name, value}, {params, name, value} ], tempile, size }, # part { headers:[ {params, name, value}, ], tempile, size }, # part { headers:[ {params, name, value}, ], tempile, size }, # part { headers:[ {params, name, value}, ], tempile, size }, # part { headers:[ {params, name, value}, ], tempile, size }, # part { headers:[ {params, name, value}, ], tempile, size }, # part ] 0、poststreamer.parts,为一个 list 对象,其总共有六个 dict(headers、tempfile、size) 元素 1、size 文件大小 2、tempfile 值是一个临时文件对象 (转存要用到) 4、headers 值是一个 list [ {params, name, value}, ] 5、六个 dict 中,第一个为需要的 """ try: file_args = {} part["tmpfile"].close() # 获取文件后缀 params = part["headers"][0].get("params", None) filename = params[ 'filename'] # 只有上传文件对应的part才有该键,通过抛出异常来获得有效文件 fill_suffix = PathUtils.get_file_suffix(filename) file_args['id'] = TimeUtils.time_id() file_args['user_id'] = user_id file_args['user_category'] = user_category_info['category'] file_args['file_category'] = 'attachment' file_args['created'] = TimeUtils.datetime_date_simple() file_args['size'] = part["size"] file_args['title'] = clean_file_name(file_title) if len(file_args['title']) == 0: file_args['title'] = str(file_args['id']) # 文件类型 full_file_type = part["headers"][1].get("value", "text/plain") if '/' in full_file_type: file_args['type'] = full_file_type.split('/')[0] elif '\\' in full_file_type: file_args['type'] = full_file_type.split('\\')[0] elif '\\\\' in full_file_type: file_args['type'] = full_file_type.split('\\\\')[0] # 文件名:id_user file_title suffix name_file = StringUtils.connect(file_args['user_category'], '_', file_args['user_id'], '-', file_args['id'], '-', file_args['title'], fill_suffix) path_folder_relative = self.make_path_folder_relative_no_static( ) path_folder_absolute = PathUtils.connect( path.PATH_STATIC, path_folder_relative) file_args['path'] = PathUtils.to_url( PathUtils.connect(path_folder_relative, name_file)) path_save = PathUtils.connect(path_folder_absolute, name_file) if isinstance(path_save, type('')): path_save = path_save.decode('utf-8') # 创建文件夹路径 if not os.path.exists(path_folder_absolute): os.makedirs(path_folder_absolute) # 转存文件(这步将临时文件保存为正式文件, 关键) os.rename(part["tmpfile"].name, path_save) if not os.path.exists(path_save): # 判断是否转存成功 file_info = {} continue file_info = file_args # break # 不能终止循环,要通过异常,来删除临时文件 except Exception as e: # traceback.print_exc() part["tmpfile"].close() os.unlink(part["tmpfile"].name) # 删除临时文件(有多个,只有一个是上传文件) # 将信息写入数据库 if len(file_info) > 0: result = self.insert_one_item(user_category_info['file_table'], **file_info) if result != -1: return { '': file_info['id'], 'file_path': file_info['path'], 'file_title': file_info['title'] } else: return {} else: return {}