FastDFS와 Redis는 사용자 정의 파일 이름을 구현하여 대용량 파일을 저장합니다.
FastDFS는 많은 양의 작은 파일을 저장하는 데 매우 적합합니다. 아쉽게도 파일 이름은 저장 성공 후 저장 위치를 기준으로 생성되는 file_id입니다. 많은 애플리케이션 시나리오는 사용자 정의 파일 이름을 사용해야 합니다. 소스 코드를 수정하지 않고 스토리지 클라이언트 fdfs_client에 데이터베이스를 추가하여 사용자 정의 파일 이름과 fastdfs의 file_id 간의 매핑 관계를 저장하여 사용자 정의 파일을 간접적으로 구현할 수 있습니다. 액세스 및 액세스, 여기서는 리드를 선택합니다. 그런데 Taobao에도 FastDFS와 유사한 파일 저장 시스템인 TFS가 있는데, 사용자 정의 파일 이름의 경우 mysql을 사용하여 매핑 관계를 저장하는데, mysql 자체가 높은 동시 액세스로 인해 병목 현상이 발생한다고 생각하므로 이 솔루션에서는 이를 사용합니다. .
준비:
fastdfs 환경 설치... 살짝... (공식: https://code.google.com/p/fastdfs/)
redis 환경 설치... 약간... (공식: http://redis.io/)
은 Python으로 구현되어 있으므로 fastdfs의 Python 클라이언트를 설치해야 합니다(다운로드: https://fastdfs. googlecode.com/files/fdfs_client-py-1.2.6.tar.gz)
Python redis 클라이언트는 https://pypi.python.org/pypi/redis
# -*- coding: utf-8 -*- import setting from fdfs_client.client import * from fdfs_client.exceptions import * from fdfs_client.connection import * import redis import time import logging import random logging.basicConfig(format='[%(levelname)s]: %(message)s', level=logging.DEBUG) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) class RedisError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class fastdfsClient(Fdfs_client): def __init__(self): self.tracker_pool = ConnectionPool(**setting.fdfs_tracker) self.timeout = setting.fdfs_tracker['timeout'] return None def __del__(self): try: self.pool.destroy() self.pool = None except: pass class fastdfs(object): def __init__(self): ''' conf_file:配置文件 ''' self.fdfs_client = fastdfsClient() self.fdfs_redis = [] for i in setting.fdfs_redis_dbs: self.fdfs_redis.append(redis.Redis(host=i[0], port=i[1], db=i[2])) def store_by_buffer(self,buf,filename=None,file_ext_name = None): ''' buffer存储文件 参数: filename:自定义文件名,如果不指定,将远程file_id作为文件名 file_ext_name:文件扩展名(可选),如果不指定,将根据自定义文件名智能判断 返回值: { 'group':组名, 'file_id':不含组名的文件ID, 'size':文件尺寸, 'upload_time':上传时间 } ''' if filename and random.choice(self.fdfs_redis).exists(filename): logger.info('File(%s) exists.'%filename) return random.choice(self.fdfs_redis).hgetall(filename) t1 = time.time() # try: ret_dict = self.fdfs_client.upload_by_buffer(buf,file_ext_name) # except Exception,e: # logger.error('Error occurred while uploading: %s'%e.message) # return None t2 = time.time() logger.info('Upload file(%s) by buffer, time consume: %fs' % (filename,(t2 - t1))) for key in ret_dict: logger.debug('[+] %s : %s' % (key, ret_dict[key])) stored_filename = ret_dict['Remote file_id'] stored_filename_without_group = stored_filename[stored_filename.index('/')+1:] if not filename: filename =stored_filename_without_group vmp = {'group':ret_dict['Group name'],'file_id':stored_filename_without_group,'size':ret_dict['Uploaded size'],'upload_time':int(time.time()*1000)} try: for i in self.fdfs_redis: if not i.hmset(filename,vmp): raise RedisError('Save Failure') logger.info('Store file(%s) by buffer successful' % filename) except Exception,e: logger.error('Save info to Redis failure. rollback...') try: ret_dict = self.fdfs_client.delete_file(stored_filename) except Exception,e: logger.error('Error occurred while deleting: %s'%e.message) return None return vmp def remove(self,filename): ''' 删除文件, filename是用户自定义文件名 return True|False ''' fileinfo = random.choice(self.fdfs_redis).hgetall(filename) stored_filename = '%s/%s'%(fileinfo['group'],fileinfo['file_id']) try: ret_dict = self.fdfs_client.delete_file(stored_filename) logger.info('Remove stored file successful') except Exception,e: logger.error('Error occurred while deleting: %s'%e.message) return False for i in self.fdfs_redis: if not i.delete(filename): logger.error('Remove fileinfo in redis failure') logger.info('%s removed.'%filename) return True def download(self,filename): ''' 下载文件 返回二进制 ''' finfo = self.getInfo(filename) if finfo: ret = self.fdfs_client.download_to_buffer('%s/%s'%(finfo['group'],finfo['file_id'])) return ret['Content'] else: logger.debug('%s is not exists'%filename) return None def list(self,pattern='*'): ''' 列出文件列表 ''' return random.choice(self.fdfs_redis).keys(pattern) def getInfo(self,filename): ''' 获得文件信息 return:{ 'group':组名, 'file_id':不含组名的文件ID, 'size':文件尺寸, 'upload_time':上传时间 } ''' return random.choice(self.fdfs_redis).hgetall(filename)
구성:
# -*- coding: utf-8 -*- #fastdfs tracker, multiple tracker supported fdfs_tracker = { 'host_tuple':('192.168.2.233','192.168.2.234'), 'port':22122, 'timeout':30, 'name':'Tracker Pool' } #fastdfs meta db, multiple redisdb supported fdfs_redis_dbs = ( ('192.168.2.233',6379,0), ('192.168.2.233',6379,1) )

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Linux 터미널에서 Python 버전을 보려고 할 때 Linux 터미널에서 Python 버전을 볼 때 권한 문제에 대한 솔루션 ... Python을 입력하십시오 ...

10 시간 이내에 컴퓨터 초보자 프로그래밍 기본 사항을 가르치는 방법은 무엇입니까? 컴퓨터 초보자에게 프로그래밍 지식을 가르치는 데 10 시간 밖에 걸리지 않는다면 무엇을 가르치기로 선택 하시겠습니까?

Fiddlerevery Where를 사용할 때 Man-in-the-Middle Reading에 Fiddlereverywhere를 사용할 때 감지되는 방법 ...

Python의 Pandas 라이브러리를 사용할 때는 구조가 다른 두 데이터 프레임 사이에서 전체 열을 복사하는 방법이 일반적인 문제입니다. 두 개의 dats가 있다고 가정 해

Uvicorn은 HTTP 요청을 어떻게 지속적으로 듣습니까? Uvicorn은 ASGI를 기반으로 한 가벼운 웹 서버입니다. 핵심 기능 중 하나는 HTTP 요청을 듣고 진행하는 것입니다 ...

Investing.com의 크롤링 전략 이해 많은 사람들이 종종 Investing.com (https://cn.investing.com/news/latest-news)에서 뉴스 데이터를 크롤링하려고합니다.

Linux 터미널에서 Python 사용 ...
