• 基于Django+FastDFS文件管理系统搭建


    FastDFS 介绍

      1. 简介

        FastDFS是一款类Google FS的开源分布式文件系统,它用纯C语言实现,支持Linux、FreeBSD、AIX等UNIX系统。它只能通过 专有API对文件进行存取访问,不支持POSIX接口方式,不能mount使用。准确地讲,Google FS以及FastDFS、mogileFS、 HDFS、TFS等类Google FS都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务。

        FastDFS 是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。

      2. 原理导图
        FastDFS架构包括 Tracker server和Storage server。客户端请求Tracker server进行文件上传、下载,通过Trackerserver调度最终由Storage server完成文件上传和下载。

        FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端 (Client)。

        Tracker Server:跟踪服务器,主要做调度工作,起到均衡的作用;负责管理所有的 storage server和 group,每个 storage 在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。通过Trackerserver在文件上传时可以根据一些策略找到Storageserver提供文件上传服务。

        Storage Server:存储服务器,主要提供容量和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份。Storage server没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。

        Client:客户端,上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。

      3. FastDFS 安装
        1、 安装FastDFS Linux依赖包

        yum install libevent libevent-devel gcc* -y
        

        2、 安装FastDFS的官方依赖包

        wget -O libfastcommon-1.0.39.tar.gz  https://codeload.github.com/happyfish100/libfastcommon/tar.gz/V1.0.39
        
        #解压依赖包
        tar -zxvf libfastcommon-1.0.39.tar.gz
        #编译安装
        cd libfastcommon-1.0.39
        ./make.sh
        ./make.sh install 
        

        3、 配置tracker
        Tracker的配置文件在/etc/fdfs/下,首先为了稳定考虑对配置文件进行备份

        cd /etc/fdfs/
        cp tracker.conf.sample tracker.conf
        vim tracker.conf
        
        #重点修改下面的几个点
        	1、	确保disable是打开的
        	disable=false
        	2、	查看提供服务的端口
        	port=22122
        	3、	指定生产tracker数据和日志的目录
        	base_path=/fastdfs/tracker
        	4、	修改默认的http端口(目的为了防止冲突)
        	http.server_port=9080
        	5、	创建tracker_base的目录
        	mkdir -p /fastdfs/tracker
        	4、	启动tracker
        	#关闭防火墙
        	systemctl stop firewalld 
        
        #启动命令
        systemctl start fdfs_trackerd
        
        #查看状态
        systemctl status fdfs_trackerd
        	```
        
        ```bash
        #如下:
        fdfs_trackerd.service - LSB: FastDFS tracker server
           Loaded: loaded (/etc/rc.d/init.d/fdfs_trackerd; bad; vendor preset: disabled)
           Active: active (running) since Mon 2020-06-22 01:53:40 EDT; 47min ago
             Docs: man:systemd-sysv-generator(8)
          Process: 1017 ExecStart=/etc/rc.d/init.d/fdfs_trackerd start (code=exited, status=0/SUCCESS)
           CGroup: /system.slice/fdfs_trackerd.service
                   └─1034 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
        
        Jun 22 01:53:40 localhost.localdomain systemd[1]: Starting LSB: FastDFS tracker server...
        Jun 22 01:53:40 localhost.localdomain fdfs_trackerd[1017]: Starting FastDFS tracker server:
        Jun 22 01:53:40 localhost.localdomain systemd[1]: Started LSB: FastDFS tracker server.
        #查看端口
        netstat -tulnp|grep fdfs
        #如下:
        tcp        0      0 0.0.0.0:22122           0.0.0.0:*               LISTEN      1034/fdfs_trackerd
        #设置tracker开机自启动
        chkconfig fdfs_trackerd on
        #关闭tracker
        /etc/init.d/fdfs_trackerd stop
        service fdfs_trackerd stop
        systemctl stop fdfs_trackerd
        

        5、 配置storage
        storage的配置文件目录同样在/etc/fdfs/

        #配置storage
        cd /etc/fdfs/
        cp storage.conf.sample storage.conf
        vim storage.conf
        确保日志当中的以下配置
        disable=false
        group_name=group1
        port=23000
        heart_beat_interval=30
        base_path=/fastdfs/storage/base
        store_path_count=1
        store_path0=/fastdfs/storage
        subdir_count_per_path=256
        tracker_server=192.168.194.158:22122
        sync_start_time=00:00
        sysc_end_time=23:59
        http.server_port=9888
        #创建对应的配置目录
        makedir -p /fastdfs/storage/base
        

        6、 启动storage

        #启动storage
        /etc/init.d/fdfs_storaged start
        service fdfs_storaged start
        systemctl start fdfs_storaged
        
        #查看状态
        systemctl status fdfs_storaged
        #如下
        ● fdfs_storaged.service - LSB: FastDFS storage server
           Loaded: loaded (/etc/rc.d/init.d/fdfs_storaged; bad; vendor preset: disabled)
           Active: active (running) since Mon 2020-06-22 01:53:40 EDT; 1h 15min ago
             Docs: man:systemd-sysv-generator(8)
          Process: 1018 ExecStart=/etc/rc.d/init.d/fdfs_storaged start (code=exited, status=0/SUCCESS)
           CGroup: /system.slice/fdfs_storaged.service
                   └─1031 /usr/bin/fdfs_storaged /etc/fdfs/storage.conf
        
        Jun 22 01:53:40 localhost.localdomain systemd[1]: Starting LSB: FastDFS storage server...
        Jun 22 01:53:40 localhost.localdomain fdfs_storaged[1018]: Starting FastDFS storage server:
        Jun 22 01:53:40 localhost.localdomain systemd[1]: Started LSB: FastDFS storage server.
        #查看端口
        netstat -unltp|grep fdfs
        tcp        0      0 0.0.0.0:23000           0.0.0.0:*               LISTEN      1031/fdfs_storaged
        #查看tracker和storage是否通信
        fdfs_monitor /etc/fdfs/storage.conf
        #如下
        ……
        server_count=1, server_index=0
        
        tracker server is 192.168.194.158:22122
        
        group count: 1
        
        Group 1:
        group name = group1
        disk total space = 17394 MB
        disk free space = 15770 MB
        trunk free space = 0 MB
        storage server count = 1
        active server count = 1
        storage server port = 23000
        storage HTTP port = 9888
        store path count = 1
        ……
        #配置storage开机启动
        chkconfig fdfs_storaged on
        
        #关闭storage
        /etc/init.d/fdfs_storaged stop
        service fdfs_storaged stop
        systemctl stop fdfs_storaged
        
        7、	配置client
        client的配置文件同样是存放在/etc/fdfs/下
        cd /etc/fdfs/
        cp client.conf.sample client.conf
        vim client.conf
        #配置如下
        base_path=/fastdfs/client
        tracker_server=192.168.194.158:22122
        

        8、 测试上传

        cd /opt/
        fdfs_upload_file /etc/fdfs/client.conf bjh.jpg
        效果如下
        group1/M00/00/00/wKjCnl7wXLSAT0pPAA8GO9kg11w732.jpg 
        Django_FastDFS使用
        	Django fastDFS有两个模块可以选择
        		py3fdfs
        		fdfs_client-py
        其中在windows下,python3环境当中使用fdfs_client-py有大概率遇到兼容问题,所以采用py3fdfs文件。
        pip install py3fdfs
        	文件上传
        
        from fdfs_client.client import Fdfs_client, get_tracker_conf
        
        tracker_path = get_tracker_conf('./client.conf')
        client = Fdfs_client(tracker_path)
        ret = client.upload_by_filename('./by.jpg')
        print(ret)
        #效果如下:
        {'Group name': b'group1', 'Remote file_id': b'group1/M00/00/00/wKjCnl7wcgCAS13GAAA6-XV4BMg226.jpg', 'Status': 'Upload successed.', 'Local file name': './by.jpg', 'Uploaded size': '14.74KB', 'Storage IP': b'192.168.194.158'}
        	    与django进行结合
        from django.shortcuts import render
        from fdfs_client.client import Fdfs_client, get_tracker_conf
        
        def index(request):
            if request.method == "POST":
                file = request.FILES.get("tfile")
                tracker_path = get_tracker_conf('./client.conf')
                client = Fdfs_client(tracker_path)
                ret = client.upload_by_buffer(file.read(),file_ext_name=file.name)
                print(ret)
            return render(request,"index.html")
        

        文件下载
        文件修改和文件下载文件删除都需要有文件的remote_file_id,这个id在文件上传的时候回返回

        #保存文件返回的数据
        {'Group name': b'group1', 'Remote file_id': b'group1/M00/00/00/wKjCnl7wcgCAS13GAAA6-XV4BMg226.jpg', 'Status': 'Upload successed.', 'Local file name': './by.jpg', 'Uploaded size': '14.74KB', 'Storage IP': b'192.168.194.158'}
        
        from fdfs_client.client import Fdfs_client, get_tracker_conf
        
        tracker_path = get_tracker_conf('./client.conf')
        client = Fdfs_client(tracker_path)
        ret = client.download_to_buffer(remote_name)
        print(ret)
        与django进行结合
        #数据建模
        from django.db import models
        
        class FileManager(models.Model):
            file_name = models.CharField(max_length = 128)
            remote_name = models.CharField(max_length = 128)
            upload_size = models.CharField(max_length = 32)
            file_type = models.CharField(max_length = 32)
            upload_time = models.DateTimeField()
            change_time = models.DateTimeField()
            group_name = models.CharField(max_length = 32)
            storage_ip = models.CharField(max_length = 64)
        
        #视图文件文件上传
        import os
        import datetime
        from django.shortcuts import render
        from django.http import JsonResponse
        from fdfs_client.client import Fdfs_client, get_tracker_conf
        
        from FileManager.models import FileManager
        
        def upload(request):
            result = {"code": "","data": [],"state": ""}
            if request.method == "POST":
                file = request.FILES.get("file")
                file_name = file.name
        
                client = os.path.join(
                    os.path.dirname(__file__),"client.conf"
                )
        
                tracker_path = get_tracker_conf(client)
                try:
                    client = Fdfs_client(tracker_path)
                    ret = client.upload_by_buffer(file.read(), file_ext_name = file_name)
                except Exception as e:
                    result["code"] = 500
                    result["state"] = str(e)
                    result["data"].append(str(e))
                else:
                    f = FileManager()
                    f.file_name = file_name
                    f.remote_name = ret.get("Remote file_id").decode()
                    f.upload_size = ret.get("Uploaded size")
                    f.file_type = "图片"
                    f.upload_time = datetime.datetime.now()
                    f.change_time = datetime.datetime.now()
                    f.group_name = ret.get("Group name").decode()
                    f.storage_ip = ret.get("Storage IP").decode()
                    f.save()
                    result["code"] = 200
                    result["state"] = "上传成功"
                    result["data"].append({
                            "file_name": file_name,
                            "file_size": f.upload_size,
                            "file_id": f.id
                    })
            else:
                result["code"] = 403
                result["state"] = "请求失败"
                result["data"].append("请求失败")
            return JsonResponse(result)
        
        #文件下载
        def download(request):
            result = {"code": "", "data": [], "state": ""}
            id_list = request.GET.getlist("file")
            for id in id_list:
                file = FileManager.objects.filter(id=id).first()
        
                if file:
                    client = os.path.join(
                        os.path.dirname(__file__), "client.conf"
                    )
                    tracker_path = get_tracker_conf(client)
                    client = Fdfs_client(tracker_path)
                    filename = file.file_name
                    remote_name = file.remote_name.replace("b'","").replace("'","")
                    with open(filename,"wb") as f:
        
                        content = client.download_to_buffer(remote_name.encode())
                        f.write(content["Content"])
                    result["code"] = 200
                    result["data"].append("下载完成")
                    result["state"] = "下载完成"
                else:
                    result["code"] = 400
                    result["data"].append("id 为 %s的文件不存在"%id)
                    result["state"] = "不完整下载"
                    continue
        
            return JsonResponse(result)
        

        版本迭代思路:
               下载文件的路径设置
                基于文件管理的用户管理系统

      4. 源码见:https://gitee.com/dazejz
  • 相关阅读:
    FlashSocke 通过flash进行socket通信(as代码)
    JavaScript 中的对象深度复制(Object Deep Clone)
    map,vector 等容器内容的循环删除问题(C++)
    [转]用JavaScript在浏览器中创建下载文件
    [记]WIndow/Linux 获取本机(全部)IPv4、IPv6、MAC地址方法 (C/C++)
    [记]Debian alias 设置, 不设置貌似有点不方便习惯
    Linux 安装配置 FTP 服务 (vsftpd)
    FreeSWITCH 安装配置的 各种坑, 填坑
    ubuntu编译安装ruby1.9.3,从p551降级到p484
    redmine3.3.3 rake db:migrate 报错invalid byte sequence in US-ASCII (Argument Error) 解决方法
  • 原文地址:https://www.cnblogs.com/bianjinhui/p/13185909.html
Copyright © 2020-2023  润新知