netty上傳文件例子
/*由于netty本身的性能需求,每次傳輸的字節數最大為1024個字節,所以如果文件內容小于1024個字節,
只需一次請求就可以上傳文件成功;如果文件內容大于1024個字節,需多次分片上傳,用到httpchunk,分片處理機制(netty本身自帶)。
一次處理不玩,分多次上傳。
*/public class UploadHandler { private static final long serialVersionUID = 1092232169163288262L; protected static String fileUploadPath = ""; protected static String fileUploadUrl = ""; protected static String imageUploadPath = ""; protected static String imageUploadUrl = ""; private boolean readingChunks = false; private FileOutputStream fOutputStream = null; private boolean isReadSuccess = true; public boolean upload(ChannelHandlerContext ctx, MessageEvent e) throws IOException{ boolean isUploadFinished=false; Channel channel = e.getChannel(); if (e.getMessage().getClass() == DefaultHttpRequest.class){ //第一次請求上傳,無論文件大小,都走該請求 DefaultHttpRequest request = (DefaultHttpRequest) e.getMessage(); if( request.isChunked() ){//netty自己分析文件大小,是否需要分片上傳文件。 readingChunks = true; }else{ ChannelBuffer buffer = request.getContent(); readFileContent(buffer); isUploadFinished=true; } } else { //netty分片上傳的實現 HttpChunk httpChunk = (HttpChunk) e.getMessage(); if (!httpChunk.isLast()){ ChannelBuffer buffer = httpChunk.getContent(); readFileContent(buffer); } else { readingChunks = false; isUploadFinished=true; } } return isUploadFinished; } private boolean readFileContent( ChannelBuffer buffer ){ try{ if (fOutputStream == null){ ByteArrayOutputStream buf = new ByteArrayOutputStream(); while( buffer.readable() ){ byte b = buffer.readByte(); buf.write(b); if( b == '\n' && new String(buf.toByteArray()).endsWith("\r\n\r\n") ) break; } String content = buf.toString("utf8"); FileItem fileItem = FileItem.parseFileItem(content); String name = fileItem.getFieldName(); if (!name.equals("file")) return false; String fileName = fileItem.getFilename(); if (fileName.indexOf("\\") > -1) { fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); } File file = new File("D://"+fileName); fOutputStream = new FileOutputStream(file); } while (buffer.readable()){ byte[] dst = new byte[buffer.readableBytes()]; buffer.readBytes(dst); fOutputStream.write(dst); } fOutputStream.flush(); return true; }catch(Exception e){ isReadSuccess=false; return false; } } }
//用于封裝請求的頭信息,獲取文件名,文件類型等信息。
class FileItem{ private String filename; private String mimeType; private String fieldName; public FileItem( String filename , String mimeType , String fieldName ) { this.filename = filename; this.mimeType = mimeType; this.fieldName = fieldName; } public static FileItem parseFileItem( String content ){ if( content == null ) return null; String filename = null; String mimeType = null; String name = null; String[] rows = content.split("\r\n"); for( String row : rows ){ int idx = row.indexOf(":"); if( idx > 0 ){ String key = row.substring(0,idx); if("Content-Disposition".equals(key)){ String val = row.substring(idx+1); String[] items = val.split(";"); for( String item : items ){ String[] kv = item.split("="); String k = kv[0].trim(); if( "name".equals(k) ){ name = kv[1].replace("\"", ""); }else if( "filename".equals(k) ){ filename = kv[1].replace("\"", ""); } } }else if( "Content-Type".equals(key) ){ String val = row.substring(idx+1); mimeType = val.trim(); } } } return new FileItem(filename, mimeType, name); } public String getFilename() { return filename; } public String getMimeType() { return mimeType; } public String getFieldName() { return fieldName; } @Override public String toString() { return String.format("name=%s mimetype=%s filename=%s", this.fieldName,this.mimeType,this.filename); } }
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!