iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Netty如何实现文件上传功能
  • 399
分享到

Netty如何实现文件上传功能

2023-06-20 14:06:23 399人浏览 八月长安
摘要

这篇文章主要讲解了“Netty如何实现文件上传功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Netty如何实现文件上传功能”吧!今天我们来完成一个使用netty进行文件传输的任务。在实际

这篇文章主要讲解了“Netty如何实现文件上传功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Netty如何实现文件上传功能”吧!

今天我们来完成一个使用netty进行文件传输的任务。在实际项目中,文件传输通常采用FTP或者Http附件的方式。事实上通过tcp Socket+File的方式进行文件传输也有一定的应用场景,尽管不是主流,但是掌握这种文件传输方式还是比较重要的,特别是针对两个跨主机的JVM进程之间进行持久化数据的相互交换。

而使用netty来进行文件传输也是利用netty天然的优势:零拷贝功能。很多同学都听说过netty的”零拷贝”功能,但是具体体现在哪里又不知道,下面我们就简要介绍下:

Netty的“零拷贝”主要体现在如下三个方面:

  • Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。

  • Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。

  • Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。

具体的分析在此就不多做介绍,有兴趣的可以查阅相关文档。我们还是把重点放在文件传输上。Netty作为高性能的服务器端异步io框架必然也离不开文件读写功能,我们可以使用netty模拟http的形式通过网页上传文件写入服务器,当然要使用http的形式那你也用不着netty!大材小用。

netty4中如果想使用http形式上传文件你还得借助第三方jar包:okhttp。使用该jar完成http请求的发送。但是在netty5 中已经为我们写好了,我们可以直接调用netty5的api就可以实现。所以netty4和5的差别还是挺大的,至于使用哪个,那就看你们公司选择哪一个了!本文目前使用netty4来实现文件上传功能。下面我们上代码:

pom文件:

<dependency>      <groupId>io.netty</groupId>        <artifactId>netty-all</artifactId>      <version>4.1.5.Final</version></dependency>

server端:

import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.Channel;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.NIO.NioEventLoopGroup;import io.netty.channel.socket.nio.NiOServerSocketChannel;import io.netty.handler.codec.serialization.ClassResolvers;import io.netty.handler.codec.serialization.ObjectDecoder;import io.netty.handler.codec.serialization.ObjectEncoder;public class FileUploadServer {    public void bind(int port) throws Exception {        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            ServerBootstrap b = new ServerBootstrap();            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChannelInitializer<Channel>() {                @Override                protected void initChannel(Channel ch) throws Exception {                    ch.pipeline().addLast(new ObjectEncoder());                    ch.pipeline().addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.weakCachinGConcurrentResolver(null))); // 最大长度                    ch.pipeline().addLast(new FileUploadServerHandler());                }            });            ChannelFuture f = b.bind(port).sync();            f.channel().closeFuture().sync();        } finally {            bossGroup.shutdownGracefully();            workerGroup.shutdownGracefully();        }    }    public static void main(String[] args) {        int port = 8080;        if (args != null && args.length > 0) {            try {                port = Integer.valueOf(args[0]);            } catch (NumberFORMatException e) {                e.printStackTrace();            }        }        try {            new FileUploadServer().bind(port);        } catch (Exception e) {            e.printStackTrace();        }    }}

server端handler:

import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import java.io.File;import java.io.RandoMaccessFile;public class FileUploadServerHandler extends ChannelInboundHandlerAdapter {    private int byteRead;    private volatile int start = 0;    private String file_dir = "D:";    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        if (msg instanceof FileUploadFile) {            FileUploadFile ef = (FileUploadFile) msg;            byte[] bytes = ef.getBytes();            byteRead = ef.getEndPos();            String md5 = ef.getFile_md5();//文件名            String path = file_dir + File.separator + md5;            File file = new File(path);            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");            randomAccessFile.seek(start);            randomAccessFile.write(bytes);            start = start + byteRead;            if (byteRead > 0) {                ctx.writeAndFlush(start);            } else {                randomAccessFile.close();                ctx.close();            }        }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }}

client端:

import io.netty.bootstrap.Bootstrap;import io.netty.channel.Channel;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.serialization.ClassResolvers;import io.netty.handler.codec.serialization.ObjectDecoder;import io.netty.handler.codec.serialization.ObjectEncoder;import java.io.File;public class FileUploadClient {    public void connect(int port, String host, final FileUploadFile fileUploadFile) throws Exception {        EventLoopGroup group = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_nodeLAY, true).handler(new ChannelInitializer<Channel>() {                @Override                protected void initChannel(Channel ch) throws Exception {                    ch.pipeline().addLast(new ObjectEncoder());                    ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(null)));                    ch.pipeline().addLast(new FileUploadClientHandler(fileUploadFile));                }            });            ChannelFuture f = b.connect(host, port).sync();            f.channel().closeFuture().sync();        } finally {            group.shutdownGracefully();        }    }    public static void main(String[] args) {        int port = 8080;        if (args != null && args.length > 0) {            try {                port = Integer.valueOf(args[0]);            } catch (NumberFormatException e) {                e.printStackTrace();            }        }        try {            FileUploadFile uploadFile = new FileUploadFile();            File file = new File("c:/1.txt");            String fileMd5 = file.getName();// 文件名            uploadFile.setFile(file);            uploadFile.setFile_md5(fileMd5);            uploadFile.setStarPos(0);// 文件开始位置            new FileUploadClient().connect(port, "127.0.0.1", uploadFile);        } catch (Exception e) {            e.printStackTrace();        }    }}

client端handler:

import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;public class FileUploadClientHandler extends ChannelInboundHandlerAdapter {    private int byteRead;    private volatile int start = 0;    private volatile int lastLength = 0;    public RandomAccessFile randomAccessFile;    private FileUploadFile fileUploadFile;    public FileUploadClientHandler(FileUploadFile ef) {        if (ef.getFile().exists()) {            if (!ef.getFile().isFile()) {                System.out.println("Not a file :" + ef.getFile());                return;            }        }        this.fileUploadFile = ef;    }    public void channelActive(ChannelHandlerContext ctx) {        try {            randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(), "r");            randomAccessFile.seek(fileUploadFile.getStarPos());            lastLength = (int) randomAccessFile.length() / 10;            byte[] bytes = new byte[lastLength];            if ((byteRead = randomAccessFile.read(bytes)) != -1) {                fileUploadFile.setEndPos(byteRead);                fileUploadFile.setBytes(bytes);                ctx.writeAndFlush(fileUploadFile);            } else {                System.out.println("文件已经读完");            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException i) {            i.printStackTrace();        }    }    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        if (msg instanceof Integer) {            start = (Integer) msg;            if (start != -1) {                randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(), "r");                randomAccessFile.seek(start);                System.out.println("块儿长度:" + (randomAccessFile.length() / 10));                System.out.println("长度:" + (randomAccessFile.length() - start));                int a = (int) (randomAccessFile.length() - start);                int b = (int) (randomAccessFile.length() / 10);                if (a < b) {                    lastLength = a;                }                byte[] bytes = new byte[lastLength];                System.out.println("-----------------------------" + bytes.length);                if ((byteRead = randomAccessFile.read(bytes)) != -1 && (randomAccessFile.length() - start) > 0) {                    System.out.println("byte 长度:" + bytes.length);                    fileUploadFile.setEndPos(byteRead);                    fileUploadFile.setBytes(bytes);                    try {                        ctx.writeAndFlush(fileUploadFile);                    } catch (Exception e) {                        e.printStackTrace();                    }                } else {                    randomAccessFile.close();                    ctx.close();                    System.out.println("文件已经读完--------" + byteRead);                }            }        }    }    // @Override    // public void channelRead(ChannelHandlerContext ctx, Object msg) throws    // Exception {    // System.out.println("Server is speek :"+msg.toString());    // FileRegion filer = (FileRegion) msg;    // String path = "E://Apk//APKMD5.txt";    // File fl = new File(path);    // fl.createNewFile();    // RandomAccessFile rdafile = new RandomAccessFile(path, "rw");    // FileRegion f = new DefaultFileRegion(rdafile.getChannel(), 0,    // rdafile.length());    //    // System.out.println("This is" + ++counter + "times receive server:["    // + msg + "]");    // }    // @Override    // public void channelReadComplete(ChannelHandlerContext ctx) throws    // Exception {    // ctx.flush();    // }    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }    // @Override    // protected void channelRead0(ChannelHandlerContext ctx, String msg)    // throws Exception {    // String a = msg;    // System.out.println("This is"+    // ++counter+"times receive server:["+msg+"]");    // }}

我们还自定义了一个对象,用于统计文件上传进度的:

import java.io.File;import java.io.Serializable;public class FileUploadFile implements Serializable {    private static final long serialVersionUID = 1L;    private File file;// 文件    private String file_md5;// 文件名    private int starPos;// 开始位置    private byte[] bytes;// 文件字节数组    private int endPos;// 结尾位置    public int getStarPos() {        return starPos;    }    public void setStarPos(int starPos) {        this.starPos = starPos;    }    public int getEndPos() {        return endPos;    }    public void setEndPos(int endPos) {        this.endPos = endPos;    }    public byte[] getBytes() {        return bytes;    }    public void setBytes(byte[] bytes) {        this.bytes = bytes;    }    public File getFile() {        return file;    }    public void setFile(File file) {        this.file = file;    }    public String getFile_md5() {        return file_md5;    }    public void setFile_md5(String file_md5) {        this.file_md5 = file_md5;    }}

输出为:

块儿长度:894
长度:8052
-----------------------------894
byte 长度:894
块儿长度:894
长度:7158
-----------------------------894
byte 长度:894
块儿长度:894
长度:6264
-----------------------------894
byte 长度:894
块儿长度:894
长度:5370
-----------------------------894
byte 长度:894
块儿长度:894
长度:4476
-----------------------------894
byte 长度:894
块儿长度:894
长度:3582
-----------------------------894
byte 长度:894
块儿长度:894
长度:2688
-----------------------------894
byte 长度:894
块儿长度:894
长度:1794
-----------------------------894
byte 长度:894
块儿长度:894
长度:900
-----------------------------894
byte 长度:894
块儿长度:894
长度:6
-----------------------------6
byte 长度:6
块儿长度:894
长度:0
-----------------------------0
文件已经读完--------0

Process finished with exit code 0

这样就实现了服务器端文件的上传,当然我们也可以使用http的形式。

server端:

import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;public class HttpFileServer implements Runnable {    private int port;    public HttpFileServer(int port) {        super();        this.port = port;    }    @Override    public void run() {        EventLoopGroup bossGroup = new NioEventLoopGroup(1);        EventLoopGroup workerGroup = new NioEventLoopGroup();        ServerBootstrap serverBootstrap = new ServerBootstrap();        serverBootstrap.group(bossGroup, workerGroup);        serverBootstrap.channel(NioServerSocketChannel.class);        //serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));        serverBootstrap.childHandler(new HttpChannelInitlalizer());        try {            ChannelFuture f = serverBootstrap.bind(port).sync();            f.channel().closeFuture().sync();        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            bossGroup.shutdownGracefully();            workerGroup.shutdownGracefully();        }    }    public static void main(String[] args) {        HttpFileServer b = new HttpFileServer(9003);        new Thread(b).start();    }}

Server端initializer:

import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.http.HttpObjectAggregator;import io.netty.handler.codec.http.httpserverCodec;import io.netty.handler.stream.ChunkedWriteHandler;public class HttpChannelInitlalizer extends ChannelInitializer<SocketChannel> {    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        pipeline.addLast(new HttpServerCodec());        pipeline.addLast(new HttpObjectAggregator(65536));        pipeline.addLast(new ChunkedWriteHandler());        pipeline.addLast(new HttpChannelHandler());    }}

server端hadler:

import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelProgressiveFuture;import io.netty.channel.ChannelProgressiveFutureListener;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.codec.http.DefaultFullHttpResponse;import io.netty.handler.codec.http.DefaultHttpResponse;import io.netty.handler.codec.http.FullHttpRequest;import io.netty.handler.codec.http.FullHttpResponse;import io.netty.handler.codec.http.HttpChunkedInput;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpResponse;import io.netty.handler.codec.http.HttpResponseStatus;import io.netty.handler.codec.http.HttpVersion;import io.netty.handler.codec.http.LastHttpContent;import io.netty.handler.stream.ChunkedFile;import io.netty.util.CharsetUtil;import io.netty.util.internal.SystemPropertyUtil;import java.io.File;import java.io.FileNotFoundException;import java.io.RandomAccessFile;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.util.regex.Pattern;import javax.activation.MimetypesFileTypeMap;public class HttpChannelHandler extends SimpleChannelInboundHandler<FullHttpRequest> {    public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";    public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";    public static final int HTTP_CACHE_SECONDS = 60;    @Override    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {        // 监测解码情况        if (!request.getDecoderResult().isSuccess()) {            sendError(ctx, BAD_REQUEST);            return;        }        final String uri = request.getUri();        final String path = sanitizeUri(uri);        System.out.println("get file:"+path);        if (path == null) {            sendError(ctx, FORBIDDEN);            return;        }        //读取要下载的文件        File file = new File(path);        if (file.isHidden() || !file.exists()) {            sendError(ctx, NOT_FOUND);            return;        }        if (!file.isFile()) {            sendError(ctx, FORBIDDEN);            return;        }        RandomAccessFile raf;        try {            raf = new RandomAccessFile(file, "r");        } catch (FileNotFoundException ignore) {            sendError(ctx, NOT_FOUND);            return;        }        long fileLength = raf.length();        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);        HttpHeaders.setContentLength(response, fileLength);        setContentTypeHeader(response, file);        //setDateAndCacheHeaders(response, file);        if (HttpHeaders.isKeepAlive(request)) {            response.headers().set("CONNECTION", HttpHeaders.Values.KEEP_ALIVE);        }        // Write the initial line and the header.        ctx.write(response);        // Write the content.        ChannelFuture sendFileFuture =        ctx.write(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)), ctx.newProgressivePromise());        //sendFuture用于监视发送数据的状态        sendFileFuture.addListener(new ChannelProgressiveFutureListener() {            @Override            public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {                if (total < 0) { // total unknown                    System.err.println(future.channel() + " Transfer progress: " + progress);                } else {                    System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);                }            }            @Override            public void operationComplete(ChannelProgressiveFuture future) {                System.err.println(future.channel() + " Transfer complete.");            }        });        // Write the end marker        ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);        // Decide whether to close the connection or not.        if (!HttpHeaders.isKeepAlive(request)) {            // Close the connection when the whole content is written out.            lastContentFuture.addListener(ChannelFutureListener.CLOSE);        }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        if (ctx.channel().isActive()) {            sendError(ctx, INTERNAL_SERVER_ERROR);        }        ctx.close();    }    private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");    private static String sanitizeUri(String uri) {        // Decode the path.        try {            uri = URLDecoder.decode(uri, "UTF-8");        } catch (UnsupportedEncodingException e) {            throw new Error(e);        }        if (!uri.startsWith("/")) {            return null;        }        // Convert file separators.        uri = uri.replace('/', File.separatorChar);        // Simplistic dumb security check.        // You will have to do something serious in the production environment.        if (uri.contains(File.separator + '.') || uri.contains('.' + File.separator) || uri.startsWith(".") || uri.endsWith(".")                || INSECURE_URI.matcher(uri).matches()) {            return null;        }        // Convert to absolute path.        return SystemPropertyUtil.get("user.dir") + File.separator + uri;    }    private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status, Unpooled.copiedBuffer("Failure: " + status + "\r\n", CharsetUtil.UTF_8));        response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");        // Close the connection as soon as the error message is sent.        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);    }        private static void setContentTypeHeader(HttpResponse response, File file) {        MimetypesFileTypeMap m = new MimetypesFileTypeMap();        String contentType = m.getContentType(file.getPath());        if (!contentType.equals("application/octet-stream")) {            contentType += "; charset=utf-8";        }        response.headers().set(CONTENT_TYPE, contentType);    }}

client端:

import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.http.DefaultFullHttpRequest;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpMethod;import io.netty.handler.codec.http.HttpRequestEncoder;import io.netty.handler.codec.http.HttpResponseDecoder;import io.netty.handler.codec.http.HttpVersion;import io.netty.handler.stream.ChunkedWriteHandler;import java.net.URI;public class HttpDownloadClient {        public void connect(String host, int port, String url, final String local) throws Exception {        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(workerGroup);            b.channel(NioSocketChannel.class);            b.option(ChannelOption.SO_KEEPALIVE, true);            b.handler(new ChildChannelHandler(local));            // Start the client.            ChannelFuture f = b.connect(host, port).sync();            URI uri = new URI(url);            DefaultFullHttpRequest request = new DefaultFullHttpRequest(                    HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString());            // 构建http请求            request.headers().set(HttpHeaders.Names.HOST, host);            request.headers().set(HttpHeaders.Names.CONNECTION,                    HttpHeaders.Values.KEEP_ALIVE);            request.headers().set(HttpHeaders.Names.CONTENT_LENGTH,                    request.content().readableBytes());            // 发送http请求            f.channel().write(request);            f.channel().flush();            f.channel().closeFuture().sync();        } finally {            workerGroup.shutdownGracefully();        }    }    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {        String local;        public ChildChannelHandler(String local) {            this.local = local;        }        @Override        protected void initChannel(SocketChannel ch) throws Exception {            // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码            ch.pipeline().addLast(new HttpResponseDecoder());            // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码            ch.pipeline().addLast(new HttpRequestEncoder());            ch.pipeline().addLast(new ChunkedWriteHandler());            ch.pipeline().addLast(new HttpDownloadHandler(local));        }    }    public static void main(String[] args) throws Exception {        HttpDownloadClient client = new HttpDownloadClient();        //client.connect("127.0.0.1", 9003,"/file/pppp/1.doc","1.doc");//        client.connect("zlysix.gree.com", 80, "http://zlysix.gree.com/HelloWEB/download/20m.apk", "20m.apk");        client.connect("www.ghost64.com", 80, "http://www.ghost64.com/qQtupian/zixunImg/local/2017/05/27/1495855297602.jpg", "1495855297602.jpg");    }}

client端handler:

import java.io.File;import java.io.FileOutputStream;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.handler.codec.http.HttpContent;//import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpResponse;import io.netty.handler.codec.http.LastHttpContent;import io.netty.util.internal.SystemPropertyUtil;public class HttpDownloadHandler extends ChannelInboundHandlerAdapter {    private boolean readingChunks = false; // 分块读取开关    private FileOutputStream fOutputStream = null;// 文件输出流    private File localfile = null;// 下载文件的本地对象    private String local = null;// 待下载文件名    private int succCode;// 状态码    public HttpDownloadHandler(String local) {        this.local = local;    }    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg)            throws Exception {        if (msg instanceof HttpResponse) {// response头信息            HttpResponse response = (HttpResponse) msg;            succCode = response.getStatus().code();            if (succCode == 200) {                setDownLoadFile();// 设置下载文件                readingChunks = true;            }            // System.out.println("CONTENT_TYPE:"            // + response.headers().get(HttpHeaders.Names.CONTENT_TYPE));        }        if (msg instanceof HttpContent) {// response体信息            HttpContent chunk = (HttpContent) msg;            if (chunk instanceof LastHttpContent) {                readingChunks = false;            }            ByteBuf buffer = chunk.content();            byte[] dst = new byte[buffer.readableBytes()];            if (succCode == 200) {                while (buffer.isReadable()) {                    buffer.readBytes(dst);                    fOutputStream.write(dst);                    buffer.release();                }                if (null != fOutputStream) {                    fOutputStream.flush();                }            }        }        if (!readingChunks) {            if (null != fOutputStream) {                System.out.println("Download done->"+ localfile.getAbsolutePath());                fOutputStream.flush();                fOutputStream.close();                localfile = null;                fOutputStream = null;            }            ctx.channel().close();        }    }        private void setDownLoadFile() throws Exception {        if (null == fOutputStream) {            local = SystemPropertyUtil.get("user.dir") + File.separator +local;            //System.out.println(local);            localfile = new File(local);            if (!localfile.exists()) {                localfile.createNewFile();            }            fOutputStream = new FileOutputStream(localfile);        }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)            throws Exception {        System.out.println("管道异常:" + cause.getMessage());        cause.printStackTrace();        ctx.channel().close();    }}

这里客户端我放的是网络连接,下载的是一副图片,启动服务端和客户端就可以看到这个图片被下载到了工程的根目录下。

Netty如何实现文件上传功能

感谢各位的阅读,以上就是“Netty如何实现文件上传功能”的内容了,经过本文的学习后,相信大家对Netty如何实现文件上传功能这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: Netty如何实现文件上传功能

本文链接: https://www.lsjlt.com/news/297310.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Netty如何实现文件上传功能
    这篇文章主要讲解了“Netty如何实现文件上传功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Netty如何实现文件上传功能”吧!今天我们来完成一个使用netty进行文件传输的任务。在实际...
    99+
    2023-06-20
  • Netty 轻松实现文件上传功能
    今天我们来完成一个使用netty进行文件传输的任务。在实际项目中,文件传输通常采用FTP或者HTTP附件的方式。事实上通过TCP Socket+File的方式进行文件传输也有一定的应...
    99+
    2024-04-02
  • SpringBoot如何实现文件上传功能
    这篇文章主要介绍了SpringBoot如何实现文件上传功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。经典的文件上传服务器处理上传文件一般都是先在请求中读取文件信息,然后改...
    99+
    2023-06-25
  • JavaWeb如何实现上传文件功能
    本篇内容主要讲解“JavaWeb如何实现上传文件功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaWeb如何实现上传文件功能”吧!这是需要使用到的两个jar包一定要导入到lib目录中,并...
    99+
    2023-07-02
  • 如何实现js上传文件功能
    这篇文章给大家分享的是有关如何实现js上传文件功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体内容如下一、用input完成上传,效果图如   ...
    99+
    2024-04-02
  • Flex上传文件功能该如何实现
    这期内容当中小编将会给大家带来有关Flex上传文件功能该如何实现,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。写过很多文件上传的功能,包括AJAX实现动态监控上传进度的,现在看到了实现Flex文件上传功能...
    99+
    2023-06-17
  • Java如何实现多文件上传功能
    这篇文章主要为大家展示了“Java如何实现多文件上传功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java如何实现多文件上传功能”这篇文章吧。文件上传是开发中十分常见的功能,在servlet...
    99+
    2023-06-20
  • thinkphp中如何实现文件上传功能
    这篇文章主要介绍“thinkphp中如何实现文件上传功能”,在日常操作中,相信很多人在thinkphp中如何实现文件上传功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”thinkphp中如何实现文件上传功能...
    99+
    2023-07-05
  • ajaxFileupload如何实现多文件上传功能
    这篇文章将为大家详细讲解有关ajaxFileupload如何实现多文件上传功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。打开google 搜索"ajaxFi...
    99+
    2024-04-02
  • javaweb实现文件上传功能
    本文实例为大家分享了javaweb实现文件上传的具体代码,供大家参考,具体内容如下 1、创建一个空项目 2、新建一个web application 的Module 3、创建一个lib...
    99+
    2024-04-02
  • JavaWeb实现上传文件功能
    本文实例为大家分享了JavaWeb实现上传文件的具体代码,供大家参考,具体内容如下 这是需要使用到的两个jar包一定要导入到lib目录中,并添加到发布的lib目录下 index.j...
    99+
    2024-04-02
  • springmvc实现文件上传功能
    一个简单的springmvc文件上传例子 所需的依赖 只需要这个就好了。在idea的依赖关系图中,commons-fileupload包含了commons-io依赖 <d...
    99+
    2024-04-02
  • ASP.NET实现文件上传功能
    本文实例为大家分享了ASP.NET实现文件上传功能的具体代码,供大家参考,具体内容如下 1、搭建网站结构 2、编写网页文件 创建一个Web窗体UploadFile和UpFile文件...
    99+
    2024-04-02
  • SpringBoot实现文件上传功能
    经典的文件上传 服务器处理上传文件一般都是先在请求中读取文件信息,然后改变名称保存在服务器的临时路径下,最后保存到服务器磁盘中。本次以thymeleaf搭建demo,因此需要引入th...
    99+
    2024-04-02
  • JSP实现文件上传功能
    本文实例为大家分享了JSP实现文件上传功能的具体代码,供大家参考,具体内容如下 一、准备部分 需要fileupload.jar与io.jar包共同完成。构建完成路径后可继续。 资源地...
    99+
    2024-04-02
  • ajaxfileupload.js实现上传文件功能
    下面是一个使用ajaxfileupload.js实现文件上传功能的示例代码:首先,你需要引入ajaxfileupload.js文件,...
    99+
    2023-08-11
    功能
  • 如何在PHP中实现文件上传功能
    在现代的Web应用开发中,文件上传功能已经成为常见的需求,无论是上传图片、视频、文档等,都需要通过服务器端的代码来实现。本文将介绍如何使用PHP来实现文件上传功能,并提供具体的代码示例。一、文件上传的基本原理在PHP中,文件上传的基本原理是...
    99+
    2023-10-21
    PHP:编程语言名称
  • bootstrap中fileinput如何实现文件上传功能
    小编给大家分享一下bootstrap中fileinput如何实现文件上传功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!boo...
    99+
    2024-04-02
  • Html5如何实现文件异步上传功能
    这篇文章主要介绍Html5如何实现文件异步上传功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1 简介开发文件上传功能从来不是一件愉快的事,异步上传更是如此,使用过iframe和F...
    99+
    2024-04-02
  • AjaxFileUpload+Struts2如何实现多文件上传功能
    这篇文章给大家分享的是有关AjaxFileUpload+Struts2如何实现多文件上传功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。单文件和多文件的实现区别主要修改两点,一...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作