美文网首页JavaJava相关技术文档
java实现图片直接上传到ftp服务器

java实现图片直接上传到ftp服务器

作者: 行者_shi | 来源:发表于2019-02-27 14:54 被阅读211次

    工作半年了,之前总是喜欢把总结和学习到的新东西放到自己OneNote上保存,方便自己回顾。但最近翻翻boss直聘上的要求,貌似写技术博客是个加分项哎,思来想去,决定以后但文档都在简上写好了,因为平时查问题的时候发现还是简书的排版最好,废话不说了开始吧!

    • pom.xml依赖引入

      <!-- ftp客户端 -->
        <dependency>
          <groupId>commons-net</groupId>
          <artifactId>commons-net</artifactId>
          <version>3.1</version>
        </dependency>
    
    • FtpUtil工具类,主要是封装了利用commons.net包下的FTPClient连接、登陆ftp服务器,并切换到ftp服务器下指定文件夹,设置上传到一些属性最后完成上传。其中的ftpIP,ftpUser, ftpPass, ftpPort都是从配置文件properties中读取的。

    public class FtpUtil {
    
        private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);
        //从properties文件读取相应的配置
        private static String ftpIP = PropertiesUtil.getProperty("ftp.server.ip");
        private static String ftpUser = PropertiesUtil.getProperty("ftp.user");
        private static String ftpPass = PropertiesUtil.getProperty("ftp.pass");
        private static String ftpPort = PropertiesUtil.getProperty("ftp.port");
    
    /**
         * 将文件直接上传到ftp服务器到方法,不会经过tomcat本地缓冲
         *
         * @param remotePath  ftp服务器中的文件夹
         * @param fileName    文件的新名称
         * @param inputStream
         * @return
         */
        public static boolean uploadFile(String remotePath, String fileName, InputStream inputStream) {
            boolean isSeccess = false;
            boolean result = false;
            FTPClient ftpClient = new FTPClient();
            try {
                //连接登陆
                ftpClient.connect(ftpIP);
                isSeccess = ftpClient.login(ftpUser, ftpPass);
                logger.info("ftp服务器:{},登陆--{}", ftpIP, isSeccess);
                //如果登陆成功...
                if (isSeccess) {
                    //切换到指定的ftp服务器文件夹目录
                    boolean isChangeSuccess = ftpClient.changeWorkingDirectory(remotePath);
                    //如果切换失败则创建改目录再切换
                    if (!isChangeSuccess) {
                        ftpClient.makeDirectory(PropertiesUtil.getProperty("ftp.dir"));
                        ftpClient.changeWorkingDirectory(remotePath);
                    }
                    //设置缓冲大小,编码格式,文件类型
                    ftpClient.setBufferSize(1024);
                    ftpClient.setControlEncoding("UTF-8");
                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                    //开始上传
                    logger.info("开始上传文件:{}", fileName);
                    result = ftpClient.storeFile(fileName, inputStream);
                    logger.info("文件:{},上传:{}", fileName, result);
                    return result;
                }
            } catch (IOException e) {
                logger.error("文件上传失败", e);
            } finally {
                try {
                    //关闭流
                    inputStream.close();
                    ftpClient.logout();
                } catch (IOException e) {
                    logger.error("输入流关闭失败", e);
                }
            }
            return result;
        }
    }
    
    • Service层主要是对上传对文件进行重命名,并封装好返回给前端的结果样式,其中ServerResponse对象是前端要求的高可用响应对象,附在最后

    @Service("iFileService")
    public class FileServiceImpl implements IFileService {
    
        //让控制台输出此文件记录内容
        private Logger logger = LoggerFactory.getLogger(FileServiceImpl.class);
    
        /**
         * 将文件直接上传至ftp服务器
         *
         * @param file
         * @return
         */
        @Override
        public ServerResponse upload(MultipartFile file) {
            Map<String, String> resultMap = new HashMap();
            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString();
            //给文件重命名
            newName = newName + oldName.substring(oldName.lastIndexOf("."));
            try {
                //利用FtpUtil中到方法进行上传文件
                boolean result = FtpUtil.uploadFile(PropertiesUtil.getProperty("ftp.dir"), newName, file.getInputStream());
                if (result) {
                    //如果上传成功,则返回前端新的文件名和路径
                    resultMap.put("uri", newName);
                    //根据nginx配置的ftp文件夹和域名的对应关系组装文件在ftp服务器中的位置
                    resultMap.put("url", PropertiesUtil.getProperty("ftp.server.http.prefix") + PropertiesUtil.getProperty("ftp.dir") + newName);
                    return ServerResponse.createBySucess(resultMap);
                } else {
                    return ServerResponse.createByErrorMessage("上传失败");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return ServerResponse.createByErrorMessage("上传失败");
        }
    }
    
    • Controller层逻辑,主要是对用户权限对校验以及文件上传

    @RequestMapping(value = "upload", method = {RequestMethod.POST})
        @ResponseBody
        public ServerResponse upload(@RequestParam(value = "file", required = true) MultipartFile file, HttpSession session) {
            User user = (User) session.getAttribute(Const.CURRENT_USER);
            if (user == null) {
                return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登陆");
            }
            if (user.getRole() != Const.ADMIN) {
                return ServerResponse.createByErrorMessage("用户无此权限");
            }
            //业务逻辑
            return iFileService.upload(file);
        }
    

    • 附:高可用响应类
    public class ServerResponse<T> implements Serializable {
        private int status;
        private String msg;
        private T data;
    
        private ServerResponse(int status) {
            this.status = status;
        }
    
        private ServerResponse(int status, T data) {
            this(status, data, null);
        }
    
        private ServerResponse(int status, T data, String msg) {
            this.status = status;
            this.data = data;
            this.msg = msg;
        }
    
        private ServerResponse(int status, String msg) {
            this(status);
            this.msg = msg;
        }
        @JsonIgnore     //json序列化到时候就不会显示这个public方法在json里面
        public boolean isSuccess() {
            return this.status == ResponseCode.SUCCESS.getCode();
        }
    
        public int getStatus() {
            return status;
        }
    
        public T getData() {
            return data;
        }
    
        public String getMsg() {
            return msg;
        }
    
        //成功时返回到数据封装ServerResponse对象
        public static <T> ServerResponse<T> createBySucess(){
            return new ServerResponse<T>(ResponseCode.SUCCESS.getCode());
        }
        public static <T> ServerResponse<T> createBySucessMsg(String msg){
            return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),msg);
        }
        public static <T> ServerResponse<T> createBySucess(T data){
            return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),data);
        }
        public static <T> ServerResponse<T> createBySucess(String msg,T data){
            return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),data,msg);
        }
    
        public static <T> ServerResponse<T> createByError(){
            return new ServerResponse<T>(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getDesc());
        }
        public static <T> ServerResponse<T> createByErrorMessage(String msg){
            return new ServerResponse<T>(ResponseCode.ERROR.getCode(),msg);
        }
        public static <T> ServerResponse<T> createByErrorCodeMessage(Integer code,String msg){
            return new ServerResponse<T>(code,msg);
        }
    }
    
    • 附:properties配置文件,其中ftp.server.http.prefix是nginx配置文件中对应ftp文件夹的那个servername
    ftp.server.ip=192.168.1.1
    ftp.user=ftpuser
    ftp.pass=123456
    ftp.server.http.prefix=http://image.test.com/
    ftp.port=21
    
    #ftp.dir=img/
    ftp.dir=video/
    
    • 这个是conf.d文件夹下自己添加的conf文件,其中的image.test.com对应的是服务器根目录下的ftpfile文件,如果只是测试,在本机hosts文件中也要配置域名和ip的对应关系。否则从返回的结果中也是无法访问的

    当在浏览器中输入image.test.com域名时,首先会从本机hosts文件查看是否有对应的ip,如果有则去访问对应的ip资源,然后会被nginx截获,并与nginx配置的域名ip对应关系对比,如果一致则可以访问资源。

    server {
        listen 80;
        autoindex on;
        server_name image.test.com;
        access_log /etc/nginx/logs/access.log combined;
        index index.html index.htm index.jsp index.php;
        #error_page 404 /404.html;
        if ( $query_string ~* ".*[\;'\<\>].*" ){
            return 404;
        }
    
        location ~ /(mmall_fe|mmall_admin_fe)/dist/view/* {
            deny all;
        }
    
        location / {
            root /ftpfile;
            add_header Access-Control-Allow-Origin *;
        }
    }
    
    
    • 最后的返回结果样式, 直接访问url后的结果
    {
        "status": 0,
        "data": {
            "uri": "05c0a49a-a461-4ab2-b277-58a1051f828c.jpeg",
            "url": "http://image.test.com/video/05c0a49a-a461-4ab2-b277-58a1051f828c.jpeg"
        }
    }
    
    //Linux服务器中ftpfile文件夹中的video文件下的上传文件
    [slf@www ftpfile]$ cd video
    [slf@www video]$ ls
    05c0a49a-a461-4ab2-b277-58a1051f828c.jpeg
    [slf@www video]$ 
    
    
    image.png

    相关文章

      网友评论

        本文标题:java实现图片直接上传到ftp服务器

        本文链接:https://www.haomeiwen.com/subject/fatfuqtx.html