def upload_voice(voice_file, duration, user, is_secure): """ 上传一个语音,保存在本地或者S3存储,并生成形如如下地址 """ # 存储安全路径还是公开路径 media_path = settings.MEDIA_PATH_PROTECT if is_secure == TRUE_STR else settings.MEDIA_PATH_PUBLIC name = safe_filename_4_shell(voice_file.name) # 生成全局唯一文件名 unique_file_name = file_storage.filename_unique(name) # 文件保存相对路径: media/{public|proteced}/voice/{school_code}/{filename}_{uuid1}.{ext} relative_path = file_storage.gen_path( os.path.join(media_path, user.school.code, 'voice'), unique_file_name) if settings.USE_S3: logger.info('uploading voice %s to s3, using PATH %s' % (voice_file.name, relative_path)) raw_md5 = s3_storage.get_operator().upload_file_obj( voice_file, relative_path) else: file_storage.save_file(voice_file, os.path.join(settings.BASE_DIR, relative_path)) ext = (name[name.rfind('.') + 1:]).lower() voice = SysVoice() voice.voice_name = name voice.voice_size = str(voice_file.size) voice.voice_duration = duration voice.voice_url = relative_path voice.voice_converted_url = relative_path voice.voice_type = ext voice.account = user voice.user_type = user.type voice.user_school = user.school voice.is_protected = int(is_secure) voice.voice_converted_status = VOICE_CONVERT_STATUS_NONE voice.save() # 异步转码 if (ext == 'wav' or ext == 'amr') and settings.IS_AUTO_CONVERT_MOV_TO_MP3: from applications.common.tasks import convert_voice try: if settings.USE_ASYNC: convert_voice.delay(voice.id) else: convert_voice(voice.id) except Exception as e: logger.exception('convert voice occur exception') return_json = { 'voice_id': str(voice.id), 'voice_name': name, 'voice_size': str(voice_file.size), 'voice_duration': type_helper.not_null_string(duration), 'voice_url': os.path.join(get_current_sys_domain(), voice.voice_url) } return return_json
def update_mobile(type, latest_version, latest_pkg, version_info): mobile = MobileDef.objects.filter(is_del=FALSE_INT, type=int(type)).first() if not mobile: raise BusinessException(CLIENT_NOT_EXIST) checksum = '' if int(type) == MOBILE_TYPE_ANDROID_PHONE: if not latest_pkg: raise BusinessException(NO_APK_ERROR) relative_path = file_storage.gen_path( os.path.join(settings.MEDIA_PATH_PUBLIC, 'packages'), latest_pkg.name) if MobileHistory.objects.filter(url=relative_path).exists(): raise BusinessException(APK_NAME_ERROR) if settings.USE_S3: checksum = s3_storage.get_operator().upload_file_obj( latest_pkg, relative_path) else: checksum = file_storage.save_file( latest_pkg, os.path.join(settings.BASE_DIR, relative_path)) returned_url = urljoin(get_current_sys_domain(), mobile.latest_version_url) elif int(type) == MOBILE_TYPE_APPLE_PHONE: if latest_pkg: raise BusinessException(IOS_HAS_APK_ERROR) relative_path = settings.IOS_DOWNLOAD returned_url = relative_path else: raise BusinessException(UNSUPPORT_TYPE_UPGRADE) # 更新当前版本数据库 mobile.latest_version = latest_version mobile.latest_version_url = relative_path mobile.latest_version_checksum = checksum mobile.version_info = version_info mobile.save() # 更新历史版本数据库 MobileHistory.objects.create(type=int(type), version=latest_version, version_info=version_info, url=relative_path) return { 'latest_version': mobile.latest_version, 'latest_version_url': returned_url }
def upload_file(file, user, is_secure, file_name=''): """ 上传一个附件,保存在本地或者S3存储 """ fname = file_name or file.name # 存储安全路径还是公开路径 media_path = settings.MEDIA_PATH_PROTECT if is_secure == TRUE_STR else settings.MEDIA_PATH_PUBLIC # 生成全局唯一文件名 unique_file_name = file_storage.filename_unique(fname) # 文件保存相对路径: media/{public|proteced}/file/{school_code}/{filename}_{uuid1}.{ext} relative_path = file_storage.gen_path( os.path.join(media_path, user.school.code, 'file'), unique_file_name) if settings.USE_S3: raw_md5 = s3_storage.get_operator().upload_file_obj( file, relative_path) else: file_storage.save_file(file, os.path.join(settings.BASE_DIR, relative_path)) sys_file = SysFile() sys_file.file_name = fname sys_file.file_size = str(file.size) sys_file.file_url = relative_path sys_file.file_type = (fname[fname.rfind('.') + 1:]).lower() sys_file.account = user sys_file.user_type = user.type sys_file.user_school = user.school sys_file.is_protected = int(is_secure) sys_file.save() return_json = { 'file_id': str(sys_file.id), 'file_url': tools.gen_url_with_fname( os.path.join(get_current_sys_domain(), sys_file.file_url), fname), 'file_size': str(file.size), 'file_name': sys_file.file_name, } return return_json
def image_handle_gif(image_file, user, is_secure): # 存储安全路径还是公开路径 media_path = _get_media_path(is_secure) # 生成全局唯一文件名 unique_file_name = file_storage.filename_unique(image_file.name) # 文件保存相对路径: media/{public|proteced}/image/{school_code}/{filename}_{uuid1}.{ext} image_repo = os.path.join(media_path, user.school.code, 'image') relative_path = file_storage.gen_path(image_repo, unique_file_name) if settings.USE_S3: md5 = s3_storage.get_operator().upload_file_obj( image_file, relative_path) else: file_storage.save_file(image_file, os.path.join(settings.BASE_DIR, relative_path)) image_to_save = SysImage() image_to_save.image_name = image_file.name image_to_save.image_size = str(image_file.size) image_to_save.image_square = ','.join( [str(each) for each in Image.open(image_file).size]) image_to_save.image_original_url = relative_path image_to_save.account = user image_to_save.user_type = user.type image_to_save.user_school = user.school image_to_save.is_protected = int(is_secure) image_to_save.image_thumb_url = relative_path image_to_save.image_crop_url = relative_path image_to_save.image_type = (image_file.name[image_file.name.rfind('.') + 1:]).lower() image_to_save.save() return_ori_path = _gen_image_download_path( image_to_save.image_original_url, image_file.name) return_thumb_path = return_ori_path return_crop_path = return_ori_path return image_to_save, return_ori_path, return_thumb_path, return_crop_path
def image_handle_common(image_file, user, is_secure): # 存储安全路径还是公开路径 media_path = _get_media_path(is_secure) # 生成全局唯一文件名 unique_file_name = file_storage.filename_unique(image_file.name) unique_thumb_name = file_storage.gen_thumb_fname(unique_file_name) unique_crop_name = file_storage.gen_crop_fname(unique_file_name) # 文件保存相对路径: media/{public|proteced}/image/{school_code}/{filename}_{uuid1}.{ext} image_repo = os.path.join(media_path, user.school.code, 'image') relative_path = file_storage.gen_path(image_repo, unique_file_name) thumb_relative_path = file_storage.gen_path(image_repo, unique_thumb_name) crop_relative_path = file_storage.gen_path(image_repo, unique_crop_name) # 依照EXIF旋转图片 try: im_after_orient = tools.pic_orientation(Image.open(image_file)) except Exception as e: logger.exception(e) raise BusinessException(INVALID_IMAGE) path_after_orient = os.path.join( file_storage.safe_folder(settings.TEMP_DIR), unique_file_name) im_after_orient.save(path_after_orient) # 处理缩略图 thumb_tmp_path = os.path.join(file_storage.safe_folder(settings.TEMP_DIR), unique_thumb_name) has_thumb = file_storage.create_thumb(path_after_orient, thumb_tmp_path) # 处理裁剪图 crop_tmp_path = os.path.join(file_storage.safe_folder(settings.TEMP_DIR), unique_crop_name) if not os.path.exists(thumb_tmp_path): has_crop = file_storage.create_crop(path_after_orient, crop_tmp_path) else: has_crop = file_storage.create_crop(thumb_tmp_path, crop_tmp_path) if settings.USE_S3: md5 = s3_storage.get_operator().upload_local_file( path_after_orient, relative_path) os.remove(path_after_orient) else: shutil.move(path_after_orient, os.path.join(settings.BASE_DIR, relative_path)) # file_storage.save_file(image_file, os.path.join(settings.BASE_DIR, relative_path)) if has_thumb: _save_local_tmp_image(thumb_tmp_path, thumb_relative_path) if has_crop: _save_local_tmp_image(crop_tmp_path, crop_relative_path) image_to_save = SysImage() image_to_save.image_name = image_file.name image_to_save.image_size = str(image_file.size) image_to_save.image_square = ','.join( [str(each) for each in Image.open(image_file).size]) image_to_save.image_original_url = relative_path image_to_save.account = user image_to_save.user_type = user.type image_to_save.user_school = user.school image_to_save.is_protected = int(is_secure) if has_thumb: image_to_save.image_thumb_url = thumb_relative_path if has_crop: image_to_save.image_crop_url = crop_relative_path image_to_save.image_type = (image_file.name[image_file.name.rfind('.') + 1:]).lower() image_to_save.save() return_ori_path = _gen_image_download_path( image_to_save.image_original_url, image_file.name) return_thumb_path = _gen_image_download_path( image_to_save.image_thumb_url or image_to_save.image_original_url, image_file.name) return_crop_path = _gen_image_download_path(image_to_save.image_crop_url, image_file.name) return image_to_save, return_ori_path, return_thumb_path, return_crop_path
def upload_video(video_file, video_duration, video_width, video_height, video_cover_image, user, is_secure): """ 上传一个视频,保存在本地或者S3存储,并生成形如如下地址: """ # 存储安全路径还是公开路径 media_path = settings.MEDIA_PATH_PROTECT if is_secure == TRUE_STR else settings.MEDIA_PATH_PUBLIC name = safe_filename_4_shell(video_file.name) # 生成全局唯一文件名 unique_file_name = file_storage.filename_unique(name) # 文件保存相对路径: media/{public|proteced}/video/{school_code}/{filename}_{uuid1}.{ext} relative_path = file_storage.gen_path( os.path.join(media_path, user.school.code, 'video'), unique_file_name) if settings.USE_S3: logger.info('uploading video %s to s3 ...' % name) raw_md5 = s3_storage.get_operator().upload_file_obj( video_file, relative_path) logger.info('upload video %s to s3 successfully' % name) else: logger.info('saving video %s to local ...' % name) file_storage.save_file(video_file, os.path.join(settings.BASE_DIR, relative_path)) logger.info('save video %s to local successfully' % name) # 视频后缀 ext = (name[name.rfind('.') + 1:]).lower() video_obj = SysVideo() # 如果包含视频封面,则保存 relative_cover_path = '' if video_cover_image: # 生成全局唯一文件名 unique_cover_name = file_storage.filename_unique( video_cover_image.name) # 文件保存相对路径: media/{public|proteced}/video_snap/{school_code}/{filename}_{uuid1}.{ext} relative_cover_path = file_storage.gen_path( os.path.join(media_path, user.school.code, 'video_snapshot'), unique_cover_name) if settings.USE_S3: raw_md5 = s3_storage.get_operator().upload_file_obj( video_cover_image, relative_cover_path) else: file_storage.save_file( video_cover_image, os.path.join(settings.BASE_DIR, relative_cover_path)) video_obj.video_snapshot_status = VIDEO_SNAPSHOT_STATUS_NONE video_obj.video_snapshot_url = relative_cover_path else: video_obj.video_snapshot_status = VIDEO_SNAPSHOT_STATUS_NONE video_obj.video_snapshot_url = None video_obj.video_name = name video_obj.video_size = str(video_file.size) video_obj.video_duration = video_duration video_obj.video_url = relative_path video_obj.video_converted_url = relative_path video_obj.video_converted_status = VIDEO_CONVERT_STATUS_NONE video_obj.video_type = ext video_obj.video_square = '%s,%s' % (str(video_width), str(video_height)) video_obj.account = user video_obj.user_type = user.type video_obj.user_school = user.school video_obj.is_protected = int(is_secure) video_obj.save() # mov格式需要异步转码 # if ext == 'mov' and settings.IS_AUTO_CONVERT_MOV_TO_MP4: # from applications.common.tasks import convert_mov # try: # if settings.USE_ASYNC: # convert_mov.delay(video_obj.id) # else: # convert_mov(video_obj.id) # except Exception as e: # logger.exception('convert video occur exception') # 是否自动压缩&转码文件 if settings.IS_AUTO_CONVERT_AND_COMPRESS_MP4: from applications.common.tasks import convert try: if settings.USE_ASYNC: convert.delay(video_obj.id) else: convert(video_obj.id) except Exception as e: logger.exception('convert and compress occur exception') # 没有截图的视频需要异步截图 # if not video_cover_image and settings.IS_AUTO_SNAPSHOT: # from applications.common.tasks import snapshot # try: # if settings.USE_ASYNC: # snapshot.delay(video_obj.id) # else: # snapshot(video_obj.id) # except Exception as e: # logger.exception('snapshot video occur exception') return_json = { 'video_id': str(video_obj.id), 'video_name': name, 'video_size': str(video_file.size), 'video_duration': type_helper.not_null_string(video_duration), 'video_width': str(video_width), 'video_height': str(video_height), 'video_url': os.path.join(get_current_sys_domain(), video_obj.video_url), 'video_cover_url': os.path.join(get_current_sys_domain(), relative_cover_path) } return return_json
def convert(video_id): logger.info('convert and compress video %d ...' % video_id) CONVERT_TMP_PATH = 'video_convert' CONVERT_TMP_PATH_ABS = file_storage.safe_folder( os.path.join(settings.TEMP_DIR, CONVERT_TMP_PATH)) video = SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).first() if not video: return SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).update( video_converted_status=VIDEO_CONVERT_STATUS_ING) media_path = settings.MEDIA_PATH_PROTECT if video.is_protected == TRUE_INT else settings.MEDIA_PATH_PUBLIC raw_fname = video.video_url[video.video_url.rfind('/') + 1:] converted_fname = raw_fname[:raw_fname.rfind('.')] + '_converted.mp4' # 转换后文件保存的相对路径 relative_path = file_storage.gen_path( os.path.join(media_path, video.user_school.code, 'video'), converted_fname) # 截图相关信息 SNAP_TMP_PATH = 'video_snapshot' SNAP_TMP_PATH_ABS = file_storage.safe_folder( os.path.join(settings.TEMP_DIR, SNAP_TMP_PATH)) snap_fname = raw_fname[:raw_fname.rfind('.')] + '_snapshot.png' snap_relative_path = file_storage.gen_path( os.path.join(media_path, video.user_school.code, 'video_snapshot'), snap_fname) if settings.USE_S3: logger.info('download (s3) video %d to convert and compress' % video_id) # 下载原始视频到本地临时目录 _key = video.video_url _local_temp_path = os.path.join(CONVERT_TMP_PATH_ABS, raw_fname) _local_temp_path_after = os.path.join(CONVERT_TMP_PATH_ABS, converted_fname) _local_temp_path_snapshot = os.path.join(SNAP_TMP_PATH_ABS, snap_fname) s3_storage.get_operator().download_file(_key, _local_temp_path) # 转码生成新视频文件 is_succ = tools.convert_and_compress(_local_temp_path, _local_temp_path_after) if is_succ: logger.info( 'convert and compress video successfully, and start uploading to s3 ...' ) raw_md5 = s3_storage.get_operator().upload_local_file( _local_temp_path_after, relative_path) logger.info('upload converted video to s3 successfully') SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).update( video_converted_status=VIDEO_CONVERT_STATUS_SUCC, video_converted_url=relative_path, ) else: logger.info('convert and compress video fail') SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).update( video_converted_status=VIDEO_CONVERT_STATUS_FAIL) is_snap_succ = tools.video_snapshot( _local_temp_path_after, _local_temp_path_snapshot) # 截图使用压缩后的视频文件 if is_snap_succ: logger.info( 'snapshot video successfully, and start uploading to s3 ...') raw_md5 = s3_storage.get_operator().upload_local_file( _local_temp_path_snapshot, snap_relative_path) logger.info('upload snapshot video to s3 successfully') snapshot_square = Image.open(_local_temp_path_snapshot).size SysVideo.objects.filter(id=video_id, is_del=FALSE_INT) \ .update(video_snapshot_status=VIDEO_SNAPSHOT_STATUS_SUCC, video_square='%d,%d' % (snapshot_square[0], snapshot_square[1]), video_snapshot_url=snap_relative_path) else: logger.error('snapshot video fail') SysVideo.objects.filter(id=video_id, is_del=FALSE_INT) \ .update(video_snapshot_status=VIDEO_SNAPSHOT_STATUS_FAIL) file_storage.safe_delete(_local_temp_path) file_storage.safe_delete(_local_temp_path_snapshot) file_storage.safe_delete(_local_temp_path_after) else: logger.info('use local video %d to convert and compress' % video_id) _local_temp_path_after = os.path.join(CONVERT_TMP_PATH_ABS, converted_fname) _local_temp_path_snapshot = os.path.join(SNAP_TMP_PATH_ABS, snap_fname) # 转码生成新视频文件 is_succ = tools.convert_and_compress( os.path.join(settings.BASE_DIR, video.video_url), _local_temp_path_after) if is_succ: logger.info('convert and compress video successfully') shutil.copy(_local_temp_path_after, os.path.join(settings.BASE_DIR, relative_path)) SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).update( video_converted_status=VIDEO_CONVERT_STATUS_SUCC, video_converted_url=relative_path, ) else: logger.info('convert and compress video fail') SysVideo.objects.filter(id=video_id, is_del=FALSE_INT).update( video_converted_status=VIDEO_CONVERT_STATUS_FAIL) is_snap_succ = tools.video_snapshot( _local_temp_path_after, _local_temp_path_snapshot) # 截图使用压缩后的视频文件 if is_snap_succ: logger.info('snapshot video successfully') snapshot_square = Image.open(_local_temp_path_snapshot).size shutil.move(_local_temp_path_snapshot, os.path.join(settings.BASE_DIR, snap_relative_path)) SysVideo.objects.filter(id=video_id, is_del=FALSE_INT) \ .update(video_square='%d,%d' % (snapshot_square[0], snapshot_square[1]), video_snapshot_status=VIDEO_SNAPSHOT_STATUS_SUCC, video_snapshot_url=relative_path) else: logger.info('snapshot video fail') SysVideo.objects.filter(id=video_id, is_del=FALSE_INT) \ .update(video_snapshot_status=VIDEO_SNAPSHOT_STATUS_FAIL) file_storage.safe_delete(_local_temp_path_snapshot) file_storage.safe_delete(_local_temp_path_after)
def convert_voice(voice_id): logger.info('convert voice %d ...' % voice_id) CONVERT_TMP_PATH = 'voice_convert' CONVERT_TMP_PATH_ABS = file_storage.safe_folder( os.path.join(settings.TEMP_DIR, CONVERT_TMP_PATH)) voice = SysVoice.objects.filter(id=voice_id).first() if not voice: return voice.voice_converted_status = VOICE_CONVERT_STATUS_ING voice.save() media_path = settings.MEDIA_PATH_PROTECT if voice.is_protected == TRUE_INT else settings.MEDIA_PATH_PUBLIC raw_fname = voice.voice_url[voice.voice_url.rfind('/') + 1:] converted_fname = raw_fname[:raw_fname.rfind('.')] + '_converted.mp3' # 转换后文件保存的相对路径 relative_path = file_storage.gen_path( os.path.join(media_path, voice.user_school.code, 'voice'), converted_fname) if settings.USE_S3: logger.info('download (s3) voice %d to convert' % voice_id) # 下载原始音频到本地临时目录 _key = voice.voice_url _local_temp_path = os.path.join(CONVERT_TMP_PATH_ABS, raw_fname) _local_temp_path_after = os.path.join(CONVERT_TMP_PATH_ABS, converted_fname) s3_storage.get_operator().download_file(_key, _local_temp_path) # 转码生成新音频文件 logger.info('convert voice %s to %s' % (_local_temp_path, _local_temp_path_after)) is_succ = tools.convert_voice_2_mp3(_local_temp_path, _local_temp_path_after) if is_succ: logger.info( 'convert voice successfully, and start uploading to s3 ...') raw_md5 = s3_storage.get_operator().upload_local_file( _local_temp_path_after, relative_path) logger.info('upload converted voice to s3 successfully') voice.voice_converted_status = VOICE_CONVERT_STATUS_SUCC voice.voice_converted_url = relative_path voice.save() else: logger.info('convert voice fail') voice.voice_converted_status = VOICE_CONVERT_STATUS_FAIL voice.save() file_storage.safe_delete(_local_temp_path) file_storage.safe_delete(_local_temp_path_after) else: logger.info('use local voice %d to convert' % voice_id) _local_temp_path_after = os.path.join(CONVERT_TMP_PATH_ABS, converted_fname) # 转码生成新音频文件 is_succ = tools.convert_voice_2_mp3( os.path.join(settings.BASE_DIR, voice.voice_url), _local_temp_path_after) if is_succ: logger.info('convert voice successfully') shutil.move(_local_temp_path_after, os.path.join(settings.BASE_DIR, relative_path)) voice.voice_converted_status = VOICE_CONVERT_STATUS_SUCC voice.voice_converted_url = relative_path voice.save() else: logger.info('convert voice fail') voice.voice_converted_status = VOICE_CONVERT_STATUS_FAIL voice.save() file_storage.safe_delete(_local_temp_path_after)