zoukankan      html  css  js  c++  java
  • 通过Fastdfs进行文件上传服务(文件和图片的统一处理)

    1、文件上传简单流程分析图:

     

    2、Fastdfs介绍:

      Fastdfs由两个角色组成:

        Tracker(集群):调度(帮你找到有空闲的Storage)

        Storage(集群):文件存储(帮你保存文件或获取需要的文件)

      流程:

        1.Storage和tracker 发送心跳连接。

        2.客户端请求tracker,tracker调度一个Storage,返回Storage的ip和端口。

        3.客户端请求Storage,上传文件。

        4.Storage保存文件,生成file_id,并返回。

        5.客户端接收到file_id并保存。

    3、上传下载流程图:

           上传:

           下载:

     

    4、Fastdfs上传具体实现步骤:

      1. 在服务器上搭建好fastdfs环境:这个由运维人员操作,开发人员无需关心。

      2. 在本地maven仓库导入fastdfs的jar包(该jar包在maven中央仓库中没有,无法通过idea自动下载,只能手动导入到本地仓库中去)

      jar包下载地址(fastdfs_client_v1.20.jar):https://sourceforge.net/projects/fastdfs/files/Java%20Client%20API%20Library/Java%20Client%20Library%20V1.20%20%28compiled%20by%20JDK%201.6%29/fastdfs_client_v1.20.jar/download?use_mirror=liquidtelecom&download=&failedmirror=jaist.dl.sourceforge.net

      导入本地仓库:

             在jar包所在的目录打开cmd,然后输入以下命令,执行后即可在maven本地仓库导入jar包并在cmd显示出jar包在仓库中的路径。

    mvn install:install-file -DgroupId=org.csource.fastdfs -DartifactId=fastdfs  -Dversion=1.2 -Dpackaging=jar -Dfile= fastdfs_client_v1.20.jar

      3. 项目中引入

    <dependency>
            <groupId>org.csource.fastdfs</groupId>
            <artifactId>fastdfs</artifactId>
            <version>1.2</version>
    </dependency>

      

      4、项目中引入以下工具类:

    fdfs_client.conf  文件(用于保存指向 tracker 的IP+端口(默认)):

    tracker_server=172.16.2.274:22122

    工具类:

    import org.csource.common.NameValuePair;
    import org.csource.fastdfs.ClientGlobal;
    import org.csource.fastdfs.StorageClient;
    import org.csource.fastdfs.StorageServer;
    import org.csource.fastdfs.TrackerClient;
    import org.csource.fastdfs.TrackerServer;
    
    public class FastDfsApiOpr {
         
        public static String CONF_FILENAME  = FastDfsApiOpr.class.getResource("/fdfs_client.conf").getFile();
    
        /**
         * 上传文件
         * @param file
         * @param extName
         * @return
         */
        public static  String upload(byte[] file,String extName) {
     
            try { 
                ClientGlobal.init(CONF_FILENAME);
     
                TrackerClient tracker = new TrackerClient(); 
                TrackerServer trackerServer = tracker.getConnection(); 
                StorageServer storageServer = null;
     
                StorageClient storageClient = new StorageClient(trackerServer, storageServer); 
                NameValuePair nvp [] = new NameValuePair[]{
                        new NameValuePair("age", "18"), 
                        new NameValuePair("sex", "male") 
                }; 
                String fileIds[] = storageClient.upload_file(file,extName,nvp);
                 
                System.out.println(fileIds.length); 
                System.out.println("组名:" + fileIds[0]); 
                System.out.println("路径: " + fileIds[1]);
                return  "/"+fileIds[0]+"/"+fileIds[1];
     
            } catch (Exception e) {
                e.printStackTrace();
                return  null;
            }
        }
    
        /**
         * 下载文件
         * @param groupName
         * @param fileName
         * @return
         */
        public static byte[] download(String groupName,String fileName) {
            try {
     
                ClientGlobal.init(CONF_FILENAME);
     
                TrackerClient tracker = new TrackerClient(); 
                TrackerServer trackerServer = tracker.getConnection(); 
                StorageServer storageServer = null;
     
                StorageClient storageClient = new StorageClient(trackerServer, storageServer); 
                byte[] b = storageClient.download_file(groupName, fileName);
                return  b;
            } catch (Exception e) {
                e.printStackTrace();
                return  null;
            } 
        }
         
    //    @Test
    //    public void testGetFileInfo(){
    //        try {
    //            ClientGlobal.init(conf_filename);
    //
    //            TrackerClient tracker = new TrackerClient();
    //            TrackerServer trackerServer = tracker.getConnection();
    //            StorageServer storageServer = null;
    //
    //            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
    //            FileInfo fi = storageClient.get_file_info("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf");
    //            System.out.println(fi.getSourceIpAddr());
    //            System.out.println(fi.getFileSize());
    //            System.out.println(fi.getCreateTimestamp());
    //            System.out.println(fi.getCrc32());
    //        } catch (Exception e) {
    //            e.printStackTrace();
    //        }
    //    }
         
    //    @Test
    //    public void testGetFileMate(){
    //        try {
    //            ClientGlobal.init(conf_filename);
    //
    //            TrackerClient tracker = new TrackerClient();
    //            TrackerServer trackerServer = tracker.getConnection();
    //            StorageServer storageServer = null;
    //
    //            StorageClient storageClient = new StorageClient(trackerServer,
    //                    storageServer);
    //            NameValuePair nvps [] = storageClient.get_metadata("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf");
    //            for(NameValuePair nvp : nvps){
    //                System.out.println(nvp.getName() + ":" + nvp.getValue());
    //            }
    //        } catch (Exception e) {
    //            e.printStackTrace();
    //        }
    //    }
    
        /**
         * 删除文件
         * @param groupName
         * @param fileName
         */
        public static void delete(String groupName,String fileName){
            try { 
                ClientGlobal.init(CONF_FILENAME);
     
                TrackerClient tracker = new TrackerClient(); 
                TrackerServer trackerServer = tracker.getConnection(); 
                StorageServer storageServer = null;
     
                StorageClient storageClient = new StorageClient(trackerServer, 
                        storageServer); 
                int i = storageClient.delete_file(groupName,fileName);
                System.out.println( i==0 ? "删除成功" : "删除失败:"+i);
            } catch (Exception e) {
                e.printStackTrace();
                throw  new RuntimeException("删除异常,"+e.getMessage());
            } 
        }
    }

      5、在contorller中使用:

    @RestController
    public class FileController {
    
        /**
         * 文件上传  MultipartFile 是SpringMVC封装好的API方便操作上传的文件的
         * @param file
         * @return
         */
        @PostMapping("/fastdfs")
        public AjaxResult upload(MultipartFile file){
    
            try {
                //获取文件的扩展名
                String filename = file.getOriginalFilename();
                String extName = filename.substring(filename.lastIndexOf(".")+1);
                String file_id = FastDfsApiOpr.upload(file.getBytes(), extName);
                return AjaxResult.me().setSuccess(true).setMessage("上传成功!").setRestObj(file_id);
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.me().setSuccess(false).setMessage("上传失败!"+e.getMessage());
            }
    
    
        }
    
        /**
         * 删除文件
         * @param file_id
         * @return
         */
        @DeleteMapping("/fastdfs")
        public AjaxResult delete(String file_id){
            try {
                //     /group1/M00/00/01/rBACgF1euQiAEdrcAACbjnUEnrE193.jpg
    
                file_id = file_id.substring(1);//   group1/M00/00/01/rBACgF1euQiAEdrcAACbjnUEnrE193.jpg
    
                String groupName = file_id.substring(0, file_id.indexOf("/"));
    
    
                String fileName = file_id.substring(file_id.indexOf("/")+1);
    
                FastDfsApiOpr.delete(groupName, fileName);
    
                return AjaxResult.me().setSuccess(true).setMessage("删除成功!");
    
            } catch (Exception e) {
                e.printStackTrace();
    
                return AjaxResult.me().setSuccess(false).setMessage("删除失败!");
    
            }
    
    
        }
    
    
    }

      5.1控制文件上传的大小

        为了解决有些文件因大于默认上传文件大小的而无法上传的问题,可以在网关模块和引用Fastdfs的controller所在的模块的启动类上加上如下代码:

     /**
         * 文件大小上传配置
         * @return
         */
        @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultipartConfigFactory factory = new MultipartConfigFactory();
            //单个文件最大
            factory.setMaxFileSize("10240KB"); //KB,MB
            /// 设置总上传数据总大小
            factory.setMaxRequestSize("102400KB");
            return factory.createMultipartConfig();
        }

      6、前端页面代码

              <el-form-item label="logo">
                        <el-upload
                                class="upload-demo"
                                action="http://localhost:6001/services/common/fastdfs"
                                :file-list="addForm.logoList"
                                list-type="picture"
                                :on-success="logoUploadSuccess"
                                :before-upload="handleBeforeUpload"
                                :on-remove="handleLogoRemove">
                            <el-button size="small" type="primary">点击上传</el-button>
                        </el-upload>
                    </el-form-item>
    methods: {
                handleLogoRemove(file, fileList){
                    //file 删除的文件
                    //调用删除文件的接口
                    let file_id = file.response.restObj
                    this.$http.delete("/common/fastdfs?file_id="+file_id)
                        .then(res=>{
                            let {success,message,restObj} = res.data;
                            if(success){
                                //fileList 删除后的文件列表
                                this.addForm.logoList = fileList;
                            }else{
                                this.$message({
                                    message:message,
                                    type:"error"
                                })
                            }
                        })
                },
                //图片上传之前的回调
                handleBeforeUpload(file){
                    if(this.addForm.logoList.length>0){
                        this.$message({
                            message:"只能上传一张图片!",
                            type:"warning"
                        })
                        return false;
                    }
                },
                //图片上传成功的回调
                logoUploadSuccess(response, file, fileList){
                    //fileList = [{response:{success:true,restObj:''}},file,file]
                    this.addForm.logoList = fileList;
                    console.log(response)
                }
    }
  • 相关阅读:
    cf1058c 暴力
    cf1058b 点是否在一个矩形里
    cf1058E 思维 前缀处理 位运算
    Codeforces Round #622 (Div. 2)C(单调栈,DP)
    Codeforces Round #623 (Div. 1, based on VK Cup 2019-2020
    Atcoder Beginner Contest 156E(隔板法,组合数学)
    【PAT甲级】1117 Eddington Number (25分)
    【PAT甲级】1116 Come on! Let's C (20分)
    【PAT甲级】1115 Counting Nodes in a BST (30分)(二叉查找树)
    Codeforces Round #621 (Div. 1 + Div. 2)E(二分查找,枚举分界点,容斥原理)
  • 原文地址:https://www.cnblogs.com/wanghj-15/p/11402962.html
Copyright © 2011-2022 走看看