news 2026/10/26 7:40:45

netty模拟文件列表http服务器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
netty模拟文件列表http服务器

学习链接

Netty网络框架 :HTTP模拟文件列表服务器

HttpObjectDecoder&HttpObjectEncoder源码浅析

ChunkedWriteHandler源码浅析

HttpPostRequestEncoder使用示例

HTTP模拟文件列表服务器

FileServer

packagecom.zzhua.file;importio.netty.bootstrap.ServerBootstrap;importio.netty.channel.ChannelFuture;importio.netty.channel.ChannelInitializer;importio.netty.channel.ChannelPipeline;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel.socket.SocketChannel;importio.netty.channel.socket.nio.NioServerSocketChannel;importio.netty.handler.codec.http.HttpObjectAggregator;importio.netty.handler.codec.http.HttpServerCodec;importio.netty.handler.logging.LoggingHandler;importio.netty.handler.stream.ChunkedWriteHandler;//通过 HTTP 请求 返回访问指定目录的文件列表publicclassFileServer{publicstaticvoidmain(String[]args){NioEventLoopGroupbossGroup=newNioEventLoopGroup();NioEventLoopGroupworkerGroup=newNioEventLoopGroup();//连接指引对象ServerBootstrapserverBootstrap=newServerBootstrap();//链式编程serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).handler(newLoggingHandler()).childHandler(newChannelInitializer<SocketChannel>(){@OverrideprotectedvoidinitChannel(SocketChannelsocketChannel)throwsException{ChannelPipelinepipeline=socketChannel.pipeline();//设定编解码器 Netty提供的http 编解码器pipeline.addLast(newHttpServerCodec());//数据聚合器 因为是分段传输 处理Http消息的聚合器pipeline.addLast(newHttpObjectAggregator(512*1024));//支持大数据的文件传输 控制对内存的使用pipeline.addLast(newChunkedWriteHandler());// 添加自定义处理器pipeline.addLast(newFileServerHandler());}});// 启动服务器try{ChannelFuturefuture=serverBootstrap.bind(9090).sync();// 阻塞关闭future.channel().closeFuture().sync();}catch(Exceptione){e.printStackTrace();}finally{workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}

FileServerHandler

packagecom.zzhua.file;importio.netty.buffer.ByteBuf;importio.netty.buffer.Unpooled;importio.netty.channel.ChannelFutureListener;importio.netty.channel.ChannelHandlerContext;importio.netty.channel.SimpleChannelInboundHandler;importio.netty.handler.codec.http.*;importio.netty.util.CharsetUtil;importjava.io.File;importjava.io.UnsupportedEncodingException;importjava.net.URLDecoder;importjava.util.regex.Pattern;/** * @projectName: gchatsystem * @package: com.hyc.gchatsystem.file * @className: FileServerHandler * @author: 冷环渊 doomwatcher * @description: TODO * @date: 2022/4/13 17:36 * @version: 1.0 *///文件服务器处理器publicclassFileServerHandlerextendsSimpleChannelInboundHandler<FullHttpRequest>{privatestaticfinalPatternINSECURE_URI=Pattern.compile(".*[<>&\"].*");//文件名称匹配规则,必须是英文、数字下划线、中划线privatestaticfinalPatternALLOWED_FILE_NAME=Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");//文件路徑privatefinalStringurl;publicFileServerHandler(){this.url="/";}@OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,FullHttpRequestrequest)throwsException{// 如果无法解码,返回400if(!request.decoderResult().isSuccess()){sendError(ctx,HttpResponseStatus.BAD_REQUEST);return;}//只支持GET方法,其他方法返回if(request.method()!=HttpMethod.GET){sendError(ctx,HttpResponseStatus.METHOD_NOT_ALLOWED);return;}//获取文件路径finalStringuri=request.uri();// 格式化URL,并且获取文件的磁盘路径finalStringpath=sanitizeUri(uri);System.out.println(path);if(path==null){sendError(ctx,HttpResponseStatus.FORBIDDEN);return;}Filefile=newFile(path);// 如果文件隐藏不可访问或者文件不存在if(file.isHidden()||!file.exists()){sendError(ctx,HttpResponseStatus.NOT_FOUND);return;}//如果是文件目录if(file.isDirectory()){//以/结尾时,就列出文件夹下的所有文件if(uri.endsWith("/")){sendListing(ctx,file);}else{//否则进行重定向,打开文件夹,继续深入sendRedirect(ctx,uri+'/');}return;}//既不是文件夹,也不是文件if(!file.isFile()){sendError(ctx,HttpResponseStatus.FORBIDDEN);}else{sendFile(ctx,request);}}privatevoidsendFile(ChannelHandlerContextctx,FullHttpRequestrequest){try{Stringuri=request.uri();Filefile=newFile(System.getProperty("user.dir")+File.separator+uri);if(!file.exists()){thrownewFileNotFoundException(file.getPath());}DefaultHttpResponseresponse=newDefaultHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK);response.headers().set(HttpHeaderNames.CONTENT_TYPE,"application/octet-stream");response.headers().set(HttpHeaderNames.CONTENT_DISPOSITION,"attachment; filename="+URLEncoder.encode(file.getName()));response.headers().set(HttpHeaderNames.CONTENT_LENGTH,file.length());ctx.writeAndFlush(response);HttpChunkedInputhttpChunkedInput=newHttpChunkedInput(newChunkedFile(file));ctx.writeAndFlush(httpChunkedInput);}catch(Exceptione){ctx.fireExceptionCaught(e);}}/** * 异常处理 */@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)throwsException{cause.printStackTrace();if(ctx.channel().isActive()){sendError(ctx,HttpResponseStatus.INTERNAL_SERVER_ERROR);}}/** * 格式化uri,返回文件的磁盘路径 * @param uri * @return * */privateStringsanitizeUri(Stringuri){try{uri=URLDecoder.decode(uri,"UTF-8");}catch(UnsupportedEncodingExceptione){//用utf-8解码出现错误时,就换种解码方式try{uri=URLDecoder.decode(uri,"ISO-8859-1");}catch(UnsupportedEncodingExceptione1){thrownewError();}}if(!uri.startsWith(url)){returnnull;}if(!uri.startsWith("/")){returnnull;}uri=uri.replace('/',File.separatorChar);if(uri.contains(File.separator+'.')||uri.contains('.'+File.separator)||uri.startsWith(".")||uri.endsWith(".")||INSECURE_URI.matcher(uri).matches()){returnnull;}System.out.println(System.getProperty("user.dir"));//returnSystem.getProperty("user.dir")+File.separator+uri;}/** * 展示文件列表 * @param ctx * @param dir * */privatestaticvoidsendListing(ChannelHandlerContextctx,Filedir){FullHttpResponseresponse=newDefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK);response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/html; charset=UTF-8");StringBuilderbuf=newStringBuilder();StringdirPath=dir.getPath();buf.append("<!DOCTYPE html>\r\n");buf.append("<html><head><title>");buf.append("使用netty做下载文件服务器");buf.append("</title></head><body>\r\n");buf.append("<h3>");buf.append("当前文件夹位置:");buf.append(dirPath);buf.append("</h3>\r\n");buf.append("<h4>");buf.append("文件列表");buf.append("</h4>\r\n");buf.append("<ul>");buf.append("<li>上一级链接:<a href=\"../\">..</a></li>\r\n");for(Filef:dir.listFiles()){//隐藏文件,不可读文件直接跳过if(f.isHidden()||!f.canRead()){continue;}Stringname=f.getName();//非英文、数字、下划线、中划线组成的文件,也跳过if(!ALLOWED_FILE_NAME.matcher(name).matches()){continue;}buf.append("<li>链接:<a href=\"");buf.append(name);buf.append("\">");buf.append(name);buf.append("</a></li>\r\n");}buf.append("</ul></body></html>\r\n");ByteBufbuffer=Unpooled.copiedBuffer(buf,CharsetUtil.UTF_8);response.content().writeBytes(buffer);buffer.release();ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}/** * 发送重定向 * @param ctx * @param newUri * */privatestaticvoidsendRedirect(ChannelHandlerContextctx,StringnewUri){FullHttpResponseresponse=newDefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.FOUND);//设置访问的url路径为新的文件夹路径response.headers().set(HttpHeaderNames.LOCATION,newUri);ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}/** * 显示错误信息 * @param ctx * @param status * */privatestaticvoidsendError(ChannelHandlerContextctx,HttpResponseStatusstatus){FullHttpResponseresponse=newDefaultFullHttpResponse(HttpVersion.HTTP_1_1,status,Unpooled.copiedBuffer("Failure: "+status.toString()+"\r\n",CharsetUtil.UTF_8));response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain; charset=UTF-8");ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 0:55:38

YOLO26模型版本管理:Git+DVC协同工作流

YOLO26模型版本管理&#xff1a;GitDVC协同工作流 在深度学习项目中&#xff0c;代码、数据和模型权重的版本管理一直是个棘手的问题。尤其是像YOLO26这样的目标检测框架&#xff0c;训练过程依赖大量数据和复杂的超参数配置&#xff0c;一旦缺乏有效的追踪机制&#xff0c;很…

作者头像 李华
网站建设 2026/10/26 9:02:50

语音转文字还能识情绪?深度体验SenseVoice Small情感识别能力

语音转文字还能识情绪&#xff1f;深度体验SenseVoice Small情感识别能力 1. 引言&#xff1a;当语音识别不再只是“听清”&#xff0c;而是“读懂” 你有没有遇到过这样的场景&#xff1f;一段客服录音&#xff0c;光看文字记录根本判断不出客户当时是满意还是愤怒&#xff…

作者头像 李华
网站建设 2026/10/26 9:48:36

MinerU能否处理扫描件?OCR增强识别实战测试

MinerU能否处理扫描件&#xff1f;OCR增强识别实战测试 1. 引言&#xff1a;扫描件提取的痛点与MinerU的潜力 你有没有遇到过这种情况&#xff1a;手头有一份重要的纸质文档&#xff0c;好不容易扫描成PDF&#xff0c;结果想提取文字时却发现——全是图片&#xff01;复制不了…

作者头像 李华
网站建设 2026/10/26 9:48:18

# 铜钱算卦与六爻模型

铜钱算卦与六爻模型 ——从古代《易》到现代系统工程的完整解析与应用定位先行 铜钱算卦 六爻&#xff0c;不是“算命工具”&#xff0c;而是一套 用随机输入 → 结构建模 → 给出行动建议 的 古代系统认知与决策模型&#xff0c;源头来自《周易》。下面这篇文案&#xff0c;按…

作者头像 李华
网站建设 2026/10/26 9:48:50

2025年AI基础设施趋势:开源Embedding模型部署实战指南

2025年AI基础设施趋势&#xff1a;开源Embedding模型部署实战指南 随着大模型技术从“生成为主”逐步迈向“理解与检索并重”&#xff0c;Embedding 模型正成为 AI 基础设施中不可或缺的一环。无论是构建智能搜索系统、实现语义推荐&#xff0c;还是支撑 RAG&#xff08;检索增…

作者头像 李华
网站建设 2026/10/26 9:48:50

5分钟部署Whisper Large v3,零基础搭建多语言语音识别服务

5分钟部署Whisper Large v3&#xff0c;零基础搭建多语言语音识别服务 1. 快速上手&#xff1a;为什么选择这个镜像&#xff1f; 你是不是也遇到过这样的问题&#xff1a;想做个语音转文字的功能&#xff0c;但模型太复杂、环境难配、语言还不全&#xff1f;今天我给你带来一…

作者头像 李华