/** * 版权所有:蚂蚁与咖啡的故事 *==================================================== * 文件名称: UploadServerHandler.java * 修订记录: * No 日期 作者(操作:具体内容) * 1. 2017-08-29 liuyuanxian(创建:创建文件) *==================================================== * 类描述:(说明未实现或其它不应生成javadoc的内容) * */ package org.lyx.file.server.support; import java.net.URI; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.handler.codec.http.DefaultHttpResponse; import org.jboss.netty.handler.codec.http.HttpChunk; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.jboss.netty.handler.codec.http.HttpVersion; import org.jboss.netty.handler.codec.http.multipart.DefaultHttpDataFactory; import org.jboss.netty.handler.codec.http.multipart.HttpDataFactory; import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder; import org.jboss.netty.util.CharsetUtil; import org.lyx.file.Constants; import org.lyx.file.server.FileServerContainer; import org.lyx.file.server.handler.factory.FileServerHandlerFactory; import org.lyx.file.server.parse.RequestParam; import org.lyx.file.server.parse.RequestParamParser; import org.lyx.file.server.utils.enumobj.EnumFileAction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * *<pre><b><font color="blue">FileServerHandler</font></b></pre> * *<pre><b>文件处理核心句柄类</b></pre> * <pre></pre> * <pre> * <b>--样例--</b> * FileServerHandler obj = new FileServerHandler(); * obj.method(); * </pre> * @author <b>landyChris</b> */ public class FileServerHandler extends SimpleChannelUpstreamHandler { private static final Logger LOGGER = LoggerFactory.getLogger(FileServerHandler.class); //http请求 private HttpRequest request; //是否需要断点续传作业 private boolean readingChunks; //接收到的文件内容 private final StringBuffer responseContent = new StringBuffer(); //解析收到的文件 private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); //16384L //post请求的解码类,它负责把字节解码成Http请求。 private HttpPostRequestDecoder decoder; //请求参数 private RequestParam requestParams = new RequestParam(); public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { if (this.decoder != null) this.decoder.cleanFiles(); } public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!this.readingChunks) { if (this.decoder != null) { this.decoder.cleanFiles(); this.decoder = null; } HttpRequest request = this.request = (HttpRequest) e.getMessage(); URI uri = new URI(request.getUri()); //如果以form开头 if (!uri.getPath().startsWith("/form")) { writeMenu(e); return; } try { //初始化decoder this.decoder = new HttpPostRequestDecoder(factory, request); } catch (HttpPostRequestDecoder.ErrorDataDecoderException e1) { e1.printStackTrace(); e1.printStackTrace(); this.responseContent.append(e1.getMessage()); writeResponse(e.getChannel()); Channels.close(e.getChannel()); return; } catch (HttpPostRequestDecoder.IncompatibleDataDecoderException e1) { e1.printStackTrace(); this.responseContent.append(e1.getMessage()); this.responseContent.append("\r\n\r\nEND OF GET CONTENT\r\n"); writeResponse(e.getChannel()); return; } if (request.isChunked()) { //说明还没有请求完成,继续 this.readingChunks = true; LOGGER.info("文件分块操作...."); } else { LOGGER.info("文件大小小于1KB,文件接收完成,直接进行相应的文件处理操作...."); //请求完成,则接收请求参数,进行初始化请求参数 RequestParamParser.parseParams(this.decoder, this.requestParams); //根据请求参数进行相应的文件操作 LOGGER.info("文件处理开始....requestParams参数解析:{}",requestParams); String result = FileServerHandlerFactory.process(this.requestParams); LOGGER.info("文件处理结束....FileServerHandlerFactory处理结果:{}",result); this.responseContent.append(result); //给客户端响应信息 writeResponse(e.getChannel()); e.getFuture().addListener(ChannelFutureListener.CLOSE); } } else { HttpChunk chunk = (HttpChunk) e.getMessage(); try { //chunk.getContent().capacity(); LOGGER.info("文件分块操作....文件大小:{} bytes",chunk.getContent().capacity()); this.decoder.offer(chunk); } catch (HttpPostRequestDecoder.ErrorDataDecoderException e1) { e1.printStackTrace(); this.responseContent.append(e1.getMessage()); writeResponse(e.getChannel()); Channels.close(e.getChannel()); return; } if (chunk.isLast()) { //文件末尾 this.readingChunks = false; LOGGER.info("到达文件内容的末尾,进行相应的文件处理操作....start"); RequestParamParser.parseParams(this.decoder, this.requestParams); LOGGER.info("文件处理开始....requestParams参数解析:{}",requestParams); String result = FileServerHandlerFactory.process(this.requestParams); LOGGER.info("文件处理结束....FileServerHandlerFactory处理结果:{}",result); this.responseContent.append(result); //给客户端响应信息 writeResponse(e.getChannel()); e.getFuture().addListener(ChannelFutureListener.CLOSE); LOGGER.info("到达文件内容的末尾,进行相应的文件处理操作....end"); } } } private void writeResponse(Channel channel) { ChannelBuffer buf = ChannelBuffers.copiedBuffer( this.responseContent.toString(), CharsetUtil.UTF_8); this.responseContent.setLength(0); boolean close = ("close".equalsIgnoreCase(this.request .getHeader("Connection"))) || ((this.request.getProtocolVersion() .equals(HttpVersion.HTTP_1_0)) && (!"keep-alive" .equalsIgnoreCase(this.request.getHeader("Connection")))); HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.setContent(buf); response.setHeader("Content-Type", "text/plain; charset=UTF-8"); if (!close) { response.setHeader("Content-Length", String.valueOf(buf.readableBytes())); } ChannelFuture future = channel.write(response); if (close) future.addListener(ChannelFutureListener.CLOSE); } private void writeMenu(MessageEvent e) { this.responseContent.setLength(0); this.responseContent.append("<html>"); this.responseContent.append("<head>"); this.responseContent.append("<title>Netty Test Form</title>\r\n"); this.responseContent.append("</head>\r\n"); this.responseContent .append("<body bgcolor=white><style>td{font-size: 12pt;}</style>"); this.responseContent.append("<table border=\"0\">"); this.responseContent.append("<tr>"); this.responseContent.append("<td>"); this.responseContent.append("<h1>Netty Test Form</h1>"); this.responseContent.append("Choose one FORM"); this.responseContent.append("</td>"); this.responseContent.append("</tr>"); this.responseContent.append("</table>\r\n"); this.responseContent .append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent .append("<FORM ACTION=\"/formget\" METHOD=\"POST\">"); this.responseContent .append("<input type=hidden name=getform value=\"POST\">"); this.responseContent.append("<table border=\"0\">"); this.responseContent .append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>"); this.responseContent .append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>"); this.responseContent .append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>"); this.responseContent.append("</td></tr>"); this.responseContent .append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>"); this.responseContent .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>"); this.responseContent.append("</table></FORM>\r\n"); this.responseContent .append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent .append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent .append("<FORM ACTION=\"/formpost\" METHOD=\"POST\">"); this.responseContent .append("<input type=hidden name=getform value=\"POST\">"); this.responseContent.append("<table border=\"0\">"); this.responseContent .append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>"); this.responseContent .append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>"); this.responseContent .append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>"); this.responseContent .append("<tr><td>Fill with file (only file name will be transmitted): <br> <input type=file name=\"myfile\">"); this.responseContent.append("</td></tr>"); this.responseContent .append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>"); this.responseContent .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>"); this.responseContent.append("</table></FORM>\r\n"); this.responseContent .append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent .append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent .append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">"); this.responseContent .append("<input type=hidden name=getform value=\"POST\">"); this.responseContent.append("<input type=hidden name=\"" + Constants.ACTION_KEY + "\" value=\"" + EnumFileAction.UPLOAD_FILE.getValue() + "\">"); this.responseContent.append("<table border=\"0\">"); this.responseContent .append("<tr><td>账户: <br> <input type=text name=\"" + Constants.USER_NAME_KEY + "\" value=\"" + Constants.DEFAULT_ACCOUNT.getUserName() + "\" size=10></td></tr>"); this.responseContent .append("<tr><td>密码: <br> <input type=text name=\"" + Constants.PWD_KEY + "\" value=\"" + Constants.DEFAULT_ACCOUNT.getPwd() + "\" size=10></td></tr>"); this.responseContent .append("<tr><td>产生缩略图: <br> <select type=file name=\"" + Constants.THUMB_MARK_KEY + "\">"); this.responseContent.append("<option value=\"" + Constants.THUMB_MARK_YES + "\">是</option>"); this.responseContent.append("<option value=\"" + Constants.THUMB_MARK_NO + "\">否</option>"); this.responseContent.append("</select></td></tr>"); this.responseContent .append("<tr><td>Fill with file: <br> <input type=file name=\"" + Constants.FILE_NAME_KEY + "\">"); this.responseContent.append("</td></tr>"); this.responseContent .append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>"); this.responseContent .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>"); this.responseContent.append("</table></FORM>\r\n"); this.responseContent .append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>"); this.responseContent.append("</body>"); this.responseContent.append("</html>"); ChannelBuffer buf = ChannelBuffers.copiedBuffer( this.responseContent.toString(), CharsetUtil.UTF_8); HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.setContent(buf); response.setHeader("Content-Type", "text/html; charset=UTF-8"); response.setHeader("Content-Length", String.valueOf(buf.readableBytes())); e.getChannel().write(response); } static { org.jboss.netty.handler.codec.http.multipart.DiskFileUpload.deleteOnExitTemporaryFile = false; org.jboss.netty.handler.codec.http.multipart.DiskFileUpload.baseDirectory = FileServerContainer .getInstance().getFileBaseDirectory(); org.jboss.netty.handler.codec.http.multipart.DiskAttribute.deleteOnExitTemporaryFile = false; org.jboss.netty.handler.codec.http.multipart.DiskAttribute.baseDirectory = FileServerContainer .getInstance().getFileBaseDirectory(); } }