package cn.gistack.by.nettyUpload; import cn.gistack.by.nettyUpload.config.NettyHttpConfig; import cn.gistack.by.nettyUpload.utils.BeenUtils; import cn.gistack.by.nettyUpload.utils.HttpResponseUtils; import cn.gistack.by.nettyUpload.utils.UriUtils; import cn.gistack.by.nettyUpload.utils.ExceptionUtils; import cn.gistack.by.picUpload.entity.BaiyiPicEntity; import cn.gistack.by.picUpload.entity.XfByPic; import cn.gistack.by.picUpload.service.BaiyiPicService; import cn.gistack.resource.feign.IOssClient; import cn.hutool.core.date.DateUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.handler.codec.http.multipart.*; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; import static cn.gistack.by.nettyUpload.utils.ExceptionUtils.getStackString; /** * 文件上传处理类 * @author chenhaijian * @date 2020-05-21 14:45 */ @Slf4j public class HttpUploadFileHandler extends SimpleChannelInboundHandler { // http请求中可选参数 private static final String FILENAME_PARAM = "filename"; // http请求中必选的参数 private static final String FILE_EXTNAME_PARAM = "fileextname"; private static final String UPLOAD_DATA_URL = "/termite/syncDeviceState"; /*** * 新设备传图片接口 */ private static final String UPLOAD_FILE_URL = "/termite/termiteDataup"; /** * 旧设备传图片接口 * 没有Authorization验证 */ private static final String UPLOAD_FILE_URL_OLD = "/termite/termiteDataupOld"; private NettyHttpConfig nettyHttpConfig; private BaiyiPicService baiyiPicService; /** * 对象存储构建类 */ private IOssClient iOssClient; static { // should delete file on exit (in normal exit) DiskFileUpload.deleteOnExitTemporaryFile = true; DiskFileUpload.baseDirectory = null; // system temp directory DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on // exit (in normal exit) DiskAttribute.baseDirectory = null; // system temp directory } public HttpUploadFileHandler(NettyHttpConfig nettyHttpConfig, IOssClient iOssClient,BaiyiPicService baiyiPicService) { this.nettyHttpConfig = nettyHttpConfig; this.iOssClient = iOssClient; this.baiyiPicService = baiyiPicService; } protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullRequest) throws Exception { // 请求路径验证 String urlyz = UriUtils.getURI(fullRequest).getPath(); log.info("请求路径urlyz::"+urlyz); if (UPLOAD_FILE_URL.equals(urlyz)) { //传图片 // Authorization验证 boolean isRequestValid = isValidHttpRequest(ctx, fullRequest); if (!isRequestValid) { HttpResponseUtils.sendResponseJson2(ctx, HttpResponseStatus.BAD_REQUEST, "验证失败",null); return ; } XfByPic xfByPic = setEntity(fullRequest); // 保存入库xfByPic baiyiPicService.inserXfPicUrl(xfByPic); }else if(UPLOAD_FILE_URL_OLD.equals(urlyz)) { // 旧类型设备上传图片数据接口 log.info("UPLOAD_FILE_URL_OLD接口调用成功!!!!:"); System.err.println(fullRequest); XfByPic xfByPic = setEntity(fullRequest); // 保存入库xfByPic baiyiPicService.inserXfOldPicUrl(xfByPic); }else if(UPLOAD_DATA_URL.equals(urlyz)) { //传数据 HttpPostMultipartRequestDecoder test = new HttpPostMultipartRequestDecoder(fullRequest); List bodyHttpDatas = test.getBodyHttpDatas(); for (InterfaceHttpData item : bodyHttpDatas ) { if ( item instanceof Attribute){ } else if (item instanceof FileUpload) { System.out.println("Attribute:::"+item.getName()); } } } else { HttpResponseUtils.sendResponseJson2(ctx, HttpResponseStatus.BAD_REQUEST, "验证失败",null); return ; } HttpResponseUtils.sendResponseJson(ctx, HttpResponseStatus.OK, "上传成功"); } //请求参数注入实体 public XfByPic setEntity(FullHttpRequest fullRequest) throws Exception { HttpPostMultipartRequestDecoder test = new HttpPostMultipartRequestDecoder(fullRequest); List bodyHttpDatas = test.getBodyHttpDatas(); XfByPic xfByPic = new XfByPic(); for (InterfaceHttpData item : bodyHttpDatas ) { if (item instanceof Attribute) { Attribute attribute = (Attribute) item; String value = attribute.getValue(); switch (attribute.getName()) { case "mnNo": xfByPic.setMnNo(value); break; case "order": xfByPic.setOrder(value); break; case "sn": xfByPic.setSn(value); break; case "ap": xfByPic.setAp(value); break; case "camera": xfByPic.setCamera(value); break; case "hardware": xfByPic.setHardware(value); break; case "rssi": xfByPic.setRssi(value); break; case "software": xfByPic.setSoftware(value); break; case "temperature": xfByPic.setTemperature(value); break; case "voltage": xfByPic.setVoltage(value); break; } } else if (item instanceof FileUpload) { FileUpload file = (FileUpload) item; String filename = file.getFilename(); ByteArrayInputStream stream = new ByteArrayInputStream(ByteBufUtil.getBytes(file.getByteBuf())); MockMultipartFile multipartFile = new MockMultipartFile("11", filename, "application/octet-stream", stream); String picurl = iOssClient.uploadFile(filename, multipartFile); log.info("图片上传地址::" + picurl); xfByPic.setImageurl(picurl); } } xfByPic.setCreatedAt(new Date()); return xfByPic; } // 请求路径验证 public String urlyz(ChannelHandlerContext ctx, FullHttpRequest request) { try { URI uri = UriUtils.getURI(request); System.err.println("uri.getPath()::::"+uri.getPath()); System.err.println(""+uri.getPath()); if (uri.getPath().startsWith(UPLOAD_DATA_URL)) { return UPLOAD_DATA_URL; } else if (uri.getPath().startsWith(UPLOAD_FILE_URL)) { return UPLOAD_FILE_URL; } else if (uri.getPath().startsWith(UPLOAD_FILE_URL_OLD)) { return UPLOAD_FILE_URL_OLD; } } catch (Exception exception) { exception.printStackTrace(); log.error(getStackString(exception)); return null; } return null; } public static MultipartFile convert(File file) throws IOException { FileInputStream input = new FileInputStream(file); MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "application/octet-stream", input); return multipartFile; } private String parseFilePath(FullHttpRequest fullRequest) throws URISyntaxException { String dirPath = this.nettyHttpConfig.getFileSaveRootPath(); String fileName = this.parseFileName(fullRequest); return dirPath + File.separator + fileName; } private RandomAccessFile getSaveFile(String filePath) { try { RandomAccessFile file = new RandomAccessFile(filePath, "rw"); return file; } catch (Exception exception) { log.error(getStackString(exception)); return null; } } private boolean isValidHttpRequest(ChannelHandlerContext ctx, FullHttpRequest request) { try { URI uri = UriUtils.getURI(request); // log.info(uri.getPath()); // authorization效验 String authorization = request.headers().get("Authorization"); if(!this.nettyHttpConfig.getAuthorization().equals(authorization)) { log.warn("Authorization校验失败!!"); // 校验不通过 HttpResponseUtils.sendResponseJson(ctx, HttpResponseStatus.UNAUTHORIZED, HttpResponseStatus.UNAUTHORIZED.toString()); // 校验不通过 return false; } // 密码校验 // boolean authFlag = auth(ctx, uri); // if (!authFlag) { // // 校验不通过 // HttpResponseUtils.sendResponseJson(ctx, HttpResponseStatus.UNAUTHORIZED, HttpResponseStatus.UNAUTHORIZED.toString()); // // 校验不通过 // return false; // } // uri 路径校验 // if (!uri.getPath().startsWith(UPLOAD_FILE_URL)) { // HttpResponseUtils.sendResponseJson(ctx, HttpResponseStatus.BAD_REQUEST,"the url must starts with /postfile"); // return false; // } return true; } catch (Exception exception) { exception.printStackTrace(); log.error(getStackString(exception)); return false; } } private String parseFileName(FullHttpRequest fullRequest) throws URISyntaxException { URI uri = UriUtils.getURI(fullRequest); Map queryParams = UriUtils.getQueryParams(uri); try { if (queryParams.containsKey(FILENAME_PARAM)) { return queryParams.get(FILENAME_PARAM); } else { SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY_MM_dd_HH_MM_SS_sss"); String filePureName = dateFormat.format(new Date()); return filePureName + "." + queryParams.get(FILE_EXTNAME_PARAM); } } catch (Exception exception) { log.error(ExceptionUtils.getStackString(exception)); return String.valueOf(System.currentTimeMillis()); } } private void writeResponse(ChannelHandlerContext ctx, String context) { ByteBuf buf = Unpooled.copiedBuffer(context, CharsetUtil.UTF_8); FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8"); //设置短连接 addListener 写完马上关闭连接 ctx.channel().writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } /** * 进行请求的密码校验 * @param ctx * @param uri * @return */ private boolean auth(ChannelHandlerContext ctx, URI uri) { Map queryParams = UriUtils.getQueryParams(uri); String passwd = queryParams.get("passwd"); if (this.nettyHttpConfig.getFileUpPasswd().equals(passwd)) { return true; } return false; } @Override public void channelInactive(ChannelHandlerContext ctx) { ctx.close(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.error(getStackString(cause)); cause.printStackTrace(); ctx.close(); } }