Netty实现FTP服务器(少点儿罗嗦,多点儿干货)

引入依赖

``

<dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty-codec-http</artifactId>
   <version>4.1.45.Final</version>
</dependency>

服务端代码

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * @author FanJiangFeng
 * @createTime 2021年12月12日 15:33:00
 *
 * FTP服务器启动类
 */
public class HttpServerDemo {

    public static void main(String[] args) throws Exception {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        ChannelFuture channelFuture = serverBootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer() {
                    protected void initChannel(Channel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new HttpServerCodec());
                        pipeline.addLast(new HttpObjectAggregator(1024));
                        pipeline.addLast(new HttpServletRequest());
                    }
                }).bind(8888);

        channelFuture.sync();
        System.out.println("FTP服务器启动成功");
    }
}

处理器代码

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import java.io.*;
import java.net.URLDecoder;

/**
 * @author FanJiangFeng
 * @createTime 2021年12月12日 15:42:00
 */
public class HttpServletRequest extends SimpleChannelInboundHandler<FullHttpRequest> {
    //文件夹路径
    private static String FILE_PATH = "D:\\工作\\表单电子化";
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception {
        //获取用户的uri
        String uri = fullHttpRequest.uri();
        //请求方式
        String name = fullHttpRequest.method().name();
        if(!"GET".equals(name)){
            responseError("只支持GET请求",channelHandlerContext);
            return;
        }
        File file = new File(FILE_PATH + URLDecoder.decode(uri, "UTF-8"));
        if (!file.exists()) {
            responseError("文件不存在。。。", channelHandlerContext);
            return;
        }
        if (file.isFile()) {
            // 如果是一个文件,就执行下载
            responseFileCopy(file, channelHandlerContext);
        } else {
            // 如果是一个目录就显示子目录
            responseDir(channelHandlerContext, file, uri);
        }
    }

    /**
     * 响应目录信息
     */
    private void responseDir(ChannelHandlerContext channelHandlerContext, File file, String uri) {
        StringBuffer buffer = new StringBuffer();
        // 获取目录的子文件
        File[] files = file.listFiles();
        for (File file1 : files) {
            if ("/".equals(uri)) {
                buffer.append("<li><a href= '" + uri + file1.getName() + "'>" + file1.getName() + "</a></li>");
            } else {
                buffer.append("<li><a href= '" + uri + File.separator + file1.getName() + "'>" + file1.getName() + "</a></li>");
            }
        }
        responseClient(buffer.toString(), channelHandlerContext);
    }

    /**
     * 文件下载
     * @param file
     * @param channelHandlerContext
     */
    private void responseFileCopy(File file, ChannelHandlerContext channelHandlerContext) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().add("Context-type", "application/octet-stream");
        response.headers().add("Content-Length", file.length());

        Channel channel = channelHandlerContext.channel();

        FileInputStream ips = null;
        try {
            ips = new FileInputStream(file);
            byte[] by = new byte[1024];
            int read = -1;
            while ((read = ips.read(by, 0, by.length)) != -1) {
                response.content().writeBytes(by, 0, read);
            }
            channel.writeAndFlush(response);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ips != null) {
                try {
                    ips.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 响应客户端
     */
    public void responseClient(String text,ChannelHandlerContext channelHandlerContext){
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        //设置响应头
        response.headers().add("Context-type","text/html;charset=UTF-8");
        String msg = "<html><meta charset=\"UTF-8\" />" + text + "</html>";
        try {
            response.content().writeBytes(msg.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        channelHandlerContext.channel().writeAndFlush(response);
    }

    /**
     * 响应错误信息
     */
    public void responseError(String text, ChannelHandlerContext channelHandlerContext) {
        String msg = "<h1>" + text + "</h1>";
        responseClient(msg, channelHandlerContext);
    }
}

效果图

在这里插入图片描述

完善后的代码

package com.ftx.camel;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import java.io.*;
import java.net.URLDecoder;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author FanJiangFeng
 * @version 1.0.0
 * @ClassName FTP.java
 * @Description TODO
 * @createTime 2022年03月24日 15:06:00
 */
public class FTP {

    //文件夹路径
    private static String FILE_PATH = "D:\\工作\\Java架构师进阶知识图谱(更新ING)";


    public static void main(String[] args) throws Exception {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        ChannelFuture channelFuture = serverBootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer() {
                    protected void initChannel(Channel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new HttpServerCodec());
                        pipeline.addLast(new HttpObjectAggregator(1024));
                        pipeline.addLast(new HttpServletRequest());
                    }
                }).bind(8888);

        channelFuture.sync();
        System.out.println("FTP服务器启动成功");
    }

     static class HttpServletRequest extends SimpleChannelInboundHandler<FullHttpRequest> {

        protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception {
            //获取用户的uri
            String uri = fullHttpRequest.uri();
            //请求方式
            String name = fullHttpRequest.method().name();
            if(!"GET".equals(name)){
                responseError("只支持GET请求",channelHandlerContext);
                return;
            }
            File file = new File(FILE_PATH + URLDecoder.decode(uri, "UTF-8"));
            if (!file.exists()) {
                responseError("文件不存在。。。", channelHandlerContext);
                return;
            }
            if (file.isFile()) {
                // 如果是一个文件,就执行下载
                responseFileCopy(file, channelHandlerContext);
            } else {
                // 如果是一个目录就显示子目录
                responseDir(channelHandlerContext, file, uri);
            }
        }

        /**
         * 响应目录信息
         */
        private void responseDir(ChannelHandlerContext channelHandlerContext, File file, String uri) {
            StringBuffer buffer = new StringBuffer();
            // 获取目录的子文件
            File[] files = file.listFiles();
            //按照文字首字母排序
            Comparator<Object> com= Collator.getInstance(java.util.Locale.CHINA);
            List<String> nameList = new ArrayList<>();
            for(File tempFile:files){
                nameList.add(tempFile.getName());
            }
            Collections.sort(nameList, com);

            buffer.append("<hr>");
            for (String name : nameList) {
                File file1 = new File(FILE_PATH + File.separator + name);
                if ("/".equals(uri)) {
                    if(file1.isDirectory()){
                        buffer.append("<li style='list-style: none;margin-left: 2%;'><img src = 'https://archive.apache.org/icons/folder.gif' />" +
                                "<a style='margin-left: 8px;font-size: 14px;\n" +
                                "    font-family: system-ui;' href= '" + uri + file1.getName() + "'>" + file1.getName() + "</a></li>");
                    }else{
                        buffer.append("<li style='list-style: none;margin-left: 2%;'><img src = 'https://archive.apache.org/icons/text.gif' />" +
                                "<a style='margin-left: 8px;font-size: 14px;\n" +
                                "    font-family: system-ui;' href= '" + uri + file1.getName() + "'>" + file1.getName() + "</a></li>");

                    }
                } else {
                    if(file1.isDirectory()){
                        buffer.append("<li style='list-style: none;margin-left: 2%;'><img src = 'https://archive.apache.org/icons/folder.gif' />" +
                                "<a style='margin-left: 8px;font-size: 14px;\n" +
                                "    font-family: system-ui;' href= '" + uri +  File.separator +file1.getName() + "'>" + file1.getName() + "</a></li>");
                    }else{
                        buffer.append("<li style='list-style: none;margin-left: 2%;'><img src = 'https://archive.apache.org/icons/text.gif' />" +
                                "<a style='margin-left: 8px;font-size: 14px;\n" +
                                "    font-family: system-ui;' href= '" + uri + File.separator + file1.getName() + "'>" + file1.getName() + "</a></li>");
                    }

                }
            }
            buffer.append("<hr>");
            responseClient(buffer.toString(), channelHandlerContext);
        }

        /**
         * 文件下载
         * @param file
         * @param channelHandlerContext
         */
        private void responseFileCopy(File file, ChannelHandlerContext channelHandlerContext) {
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            response.headers().add("Context-type", "application/octet-stream");
            response.headers().add("Content-Length", file.length());

            Channel channel = channelHandlerContext.channel();

            FileInputStream ips = null;
            try {
                ips = new FileInputStream(file);
                byte[] by = new byte[1024];
                int read = -1;
                while ((read = ips.read(by, 0, by.length)) != -1) {
                    response.content().writeBytes(by, 0, read);
                }
                channel.writeAndFlush(response);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (ips != null) {
                    try {
                        ips.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * 响应客户端
         */
        public void responseClient(String text,ChannelHandlerContext channelHandlerContext){
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            //设置响应头
            response.headers().add("Context-type","text/html;charset=UTF-8");
            String msg = "<html><meta charset=\"UTF-8\" />" + text + "</html>";
            try {
                response.content().writeBytes(msg.getBytes("UTF-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            channelHandlerContext.channel().writeAndFlush(response);
            channelHandlerContext.channel().close();
        }

        /**
         * 响应错误信息
         */
        public void responseError(String text, ChannelHandlerContext channelHandlerContext) {
            String msg = "<h1>" + text + "</h1>";
            responseClient(msg, channelHandlerContext);
        }
    }
}

完善后的效果图

posted @ 2021-12-12 16:33  你樊不樊  阅读(39)  评论(0)    收藏  举报