<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot集成Netty實現(xiàn)文件傳輸

          共 5398字,需瀏覽 11分鐘

           ·

          2020-10-24 05:30

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          ? 作者?|??47號Gamer丶

          來源 |? urlify.cn/bIzUZb

          66套java從入門到精通實戰(zhàn)課程分享

          實現(xiàn)瀏覽本地文件目錄,實現(xiàn)文件夾目錄的跳轉和文件的下載

          添加依賴:


          ????org.springframework.boot
          ????spring-boot-starter-web
          ????
          ????????
          ????????????org.springframework.boot
          ????????????spring-boot-starter-tomcat
          ????????

          ????



          ????io.netty
          ????netty-all
          ????4.1.1.Final


          ????commons-lang
          ????commons-lang
          ????${commons.lang.version}

          排除tomcat的依賴

          Netty Http服務端編寫:

          handler 處理類

          @Component
          @Slf4j
          @ChannelHandler.Sharable?//@Sharable?注解用來說明ChannelHandler是否可以在多個channel直接共享使用
          public?class?FileServerHandler?extends?ChannelInboundHandlerAdapter?{

          ???//?private?static?final?Pattern?ALLOWED_FILE_NAME?=?Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");

          ????//文件存放路徑
          ????@Value("${netty.file.path:}")
          ????String?path;

          ????@Override
          ????public?void?channelRead(ChannelHandlerContext?ctx,?Object?msg)?{
          ????????try{
          ????????????if?(msg?instanceof?FullHttpRequest)?{
          ????????????????FullHttpRequest?req?=?(FullHttpRequest)?msg;
          ????????????????if(req.method()?!=?HttpMethod.GET)?{
          ????????????????????sendError(ctx,?HttpResponseStatus.METHOD_NOT_ALLOWED);
          ????????????????????return;
          ????????????????}
          ????????????????String?url?=?req.uri();
          ????????????????File?file?=?new?File(path?+?url);
          ????????????????if(file.exists()){
          ????????????????????if(file.isDirectory()){
          ????????????????????????if(url.endsWith("/"))?{
          ????????????????????????????sendListing(ctx,?file);
          ????????????????????????}else{
          ????????????????????????????sendRedirect(ctx,?url?+?"/");
          ????????????????????????}
          ????????????????????????return;
          ????????????????????}else?{
          ????????????????????????transferFile(?file,??ctx);
          ????????????????????}
          ????????????????}else{
          ????????????????????sendError(ctx,?HttpResponseStatus.NOT_FOUND);
          ????????????????}
          ????????????}
          ????????}catch(Exception?e){
          ????????????log.error("Exception:{}",e);
          ????????????sendError(ctx,?HttpResponseStatus.BAD_REQUEST);
          ????????}
          ????}

          ????/**
          ?????*?傳輸文件
          ?????*?@param?file
          ?????*?@param?ctx
          ?????*/
          ????private?void?transferFile(File?file,?ChannelHandlerContext?ctx){
          ????????try{
          ????????????RandomAccessFile?randomAccessFile?=?new?RandomAccessFile(file,?"r");
          ????????????long?fileLength?=?randomAccessFile.length();
          ????????????HttpResponse?response?=?new?DefaultHttpResponse(HttpVersion.HTTP_1_1,?HttpResponseStatus.OK);
          ????????????response.headers().set(HttpHeaderNames.CONTENT_LENGTH,?fileLength);
          ????????????ctx.write(response);
          ????????????ChannelFuture?sendFileFuture?=?ctx.write(new?ChunkedFile(randomAccessFile,?0,?fileLength,?8192),?ctx.newProgressivePromise());
          ????????????addListener(?sendFileFuture);
          ????????????ChannelFuture?lastContentFuture?=?ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
          ????????????lastContentFuture.addListener(ChannelFutureListener.CLOSE);
          ????????}catch?(Exception?e){
          ????????????log.error("Exception:{}",e);
          ????????}
          ????}

          ????/**
          ?????*?監(jiān)聽傳輸狀態(tài)
          ?????*?@param?sendFileFuture
          ?????*/
          ????private?void?addListener(?ChannelFuture?sendFileFuture){
          ????????sendFileFuture.addListener(new?ChannelProgressiveFutureListener()?{
          ????????????????@Override
          ????????????????public?void?operationComplete(ChannelProgressiveFuture?future)
          ????????????????????????throws?Exception?{
          ????????????????????log.debug("Transfer?complete.");
          ????????????????}
          ????????????????@Override
          ????????????????public?void?operationProgressed(ChannelProgressiveFuture?future,?long?progress,?long?total)?throws?Exception?{
          ????????????????????if(total?????????????????????????log.debug("Transfer?progress:?"?+?progress);
          ????????????????????}else{
          ????????????????????????log.debug("Transfer?progress:?"?+?progress?+?"/"?+?total);
          ????????????????????}
          ????????????????}
          ????????});
          ????}


          ????/**
          ?????*?請求為目錄時,顯示文件列表
          ?????*?@param?ctx
          ?????*?@param?dir
          ?????*/
          ????private?static?void?sendListing(ChannelHandlerContext?ctx,?File?dir){
          ????????FullHttpResponse?response?=?new?DefaultFullHttpResponse(HttpVersion.HTTP_1_1,?HttpResponseStatus.OK);
          ????????response.headers().set(HttpHeaderNames.CONTENT_TYPE,?"text/html;charset=UTF-8");

          ????????String?dirPath?=?dir.getPath();
          ????????StringBuilder?buf?=?new?StringBuilder();

          ????????buf.append("\r\n");
          ????????buf.append(""</span>);<br>????????buf.append(dirPath);<br>????????buf.append(<span style="color: #98c379;line-height: 26px;">"目錄:"</span>);<br>????????buf.append(<span style="color: #98c379;line-height: 26px;">"\r\n");

          ????????buf.append("

          ");
          ????????buf.append(dirPath).append("?目錄:");
          ????????buf.append("

          \r\n"
          );
          ????????buf.append("\r\n");
          ????????ByteBuf?buffer?=?Unpooled.copiedBuffer(buf,CharsetUtil.UTF_8);
          ????????response.content().writeBytes(buffer);
          ????????buffer.release();
          ????????ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
          ????}

          ????/**
          ?????*?跳轉鏈接
          ?????*?@param?ctx
          ?????*?@param?newUri
          ?????*/
          ????private?static?void?sendRedirect(ChannelHandlerContext?ctx,?String?newUri){
          ????????FullHttpResponse?response?=?new?DefaultFullHttpResponse(HttpVersion.HTTP_1_1,?HttpResponseStatus.FOUND);
          ????????response.headers().set(HttpHeaderNames.LOCATION,?newUri);
          ????????ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
          ????}

          ????/**
          ?????*?失敗響應
          ?????*?@param?ctx
          ?????*?@param?status
          ?????*/
          ????private?static?void?sendError(ChannelHandlerContext?ctx,?HttpResponseStatus?status){
          ????????FullHttpResponse?response?=?new?DefaultFullHttpResponse(HttpVersion.HTTP_1_1,?status,
          ????????????????Unpooled.copiedBuffer("Failure:?"?+?status.toString()?+?"\r\n",?CharsetUtil.UTF_8));
          ????????response.headers().set(HttpHeaderNames.CONTENT_TYPE,?"text/html;charset=UTF-8");
          ????????ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
          ????}


          }

          ChannelPipeline 實現(xiàn):

          @Component
          @ConditionalOnProperty(??//配置文件屬性是否為true
          ????????value?=?{"netty.file.enabled"},
          ????????matchIfMissing?=?false
          )
          public?class?FilePipeline?extends?ChannelInitializer?{

          ????@Autowired
          ????FileServerHandler?fleServerHandler;

          ????@Override
          ????protected?void?initChannel(SocketChannel?socketChannel)?throws?Exception?{
          ????????ChannelPipeline?p?=?socketChannel.pipeline();
          ????????p.addLast("http-decoder",?new?HttpRequestDecoder());
          ????????p.addLast("http-aggregator",?new?HttpObjectAggregator(65536));
          ????????p.addLast("http-encoder",?new?HttpResponseEncoder());
          ????????p.addLast("http-chunked",?new?ChunkedWriteHandler());
          ????????p.addLast("fileServerHandler",fleServerHandler);
          ????}
          }

          服務實現(xiàn):

          @Configuration
          @EnableConfigurationProperties({NettyFileProperties.class})
          @ConditionalOnProperty(??//配置文件屬性是否為true
          ????????value?=?{"netty.file.enabled"},
          ????????matchIfMissing?=?false
          )
          @Slf4j
          public?class?FileServer?{
          ????@Autowired
          ????FilePipeline?filePipeline;

          ????@Autowired
          ????NettyFileProperties?nettyFileProperties;

          ????@Bean("starFileServer")
          ????public?String?start()?{
          ????????Thread?thread?=??new?Thread(()?->?{
          ????????????NioEventLoopGroup?bossGroup?=?new?NioEventLoopGroup(nettyFileProperties.getBossThreads());
          ????????????NioEventLoopGroup?workerGroup?=?new?NioEventLoopGroup(nettyFileProperties.getWorkThreads());
          ????????????try?{
          ????????????????log.info("start?netty?[FileServer]?server?,port:?"?+?nettyFileProperties.getPort());
          ????????????????ServerBootstrap?boot?=?new?ServerBootstrap();
          ????????????????options(boot).group(bossGroup,?workerGroup)
          ????????????????????????.channel(NioServerSocketChannel.class)
          ????????????????????????.handler(new?LoggingHandler(LogLevel.INFO))
          ????????????????????????.childHandler(filePipeline);
          ????????????????Channel?ch?=?null;
          ??????????????//是否綁定IP
          ????????????????if(StringUtils.isNotEmpty(nettyFileProperties.getBindIp())){
          ????????????????????ch?=?boot.bind(nettyFileProperties.getBindIp(),nettyFileProperties.getPort()).sync().channel();
          ????????????????}else{
          ????????????????????ch?=?boot.bind(nettyFileProperties.getPort()).sync().channel();
          ????????????????}
          ????????????????ch.closeFuture().sync();
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????log.error("啟動NettyServer錯誤",?e);
          ????????????}?finally?{
          ????????????????bossGroup.shutdownGracefully();
          ????????????????workerGroup.shutdownGracefully();
          ????????????}
          ????????});
          ????????thread.setName("File_Server");
          ????????thread.start();
          ????????return?"file?start";
          ????}


          ????private?ServerBootstrap?options(ServerBootstrap?boot)?{
          ?/*???????boot.option(ChannelOption.SO_BACKLOG,?1024)
          ????????????????.option(ChannelOption.TCP_NODELAY,?true)
          ????????????????.option(ChannelOption.ALLOCATOR,?PooledByteBufAllocator.DEFAULT);*/
          ????????return?boot;
          ????}
          }

          啟動配置:

          ---application.yml
          spring.profiles.active:?file

          ---application-file.yml
          netty:
          ???file:
          ?????enabled:?true
          ?????path:?d:\
          ?????port:?3456

          測試

          在瀏覽器打開http://127.0.0.1:3456/

          ?



          粉絲福利:108本java從入門到大神精選電子書領取

          ???

          ?長按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進入java1234官方微信群



          感謝點贊支持下哈?

          瀏覽 83
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美日韩色视频 | 国产欧美日韩视频在线 | 亚洲国产成人在线播放 | 亚洲少妇婷婷 | 人人塞人人艹 |