/*由于netty本身的性能需求,每次传输的字节数最大为1024个字节,所以如果文件内容小于1024个字节,
只需一次请求就可以上传文件成功;如果文件内容大于1024个字节,需多次分片上传,用到httpchunk,分片处理机制(netty本身自带)。
一次处理不玩,分多次上传。
//用于封装请求的头信息,获取文件名,文件类型等信息。
只需一次请求就可以上传文件成功;如果文件内容大于1024个字节,需多次分片上传,用到httpchunk,分片处理机制(netty本身自带)。
一次处理不玩,分多次上传。
01 | */ public class UploadHandler { |
02 | private static final long serialVersionUID = 1092232169163288262L; |
03 | protected static String fileUploadPath = "" ; |
04 | protected static String fileUploadUrl = "" ; |
05 | protected static String imageUploadPath = "" ; |
06 | protected static String imageUploadUrl = "" ; |
07 |
08 | private boolean readingChunks = false ; |
09 | private FileOutputStream fOutputStream = null ; |
10 | private boolean isReadSuccess = true ; |
11 | |
12 | public boolean upload(ChannelHandlerContext ctx, MessageEvent e) throws IOException{ |
13 | boolean isUploadFinished= false ; |
14 | Channel channel = e.getChannel(); |
15 | if (e.getMessage().getClass() == DefaultHttpRequest. class ){ //第一次请求上传,无论文件大小,都走该请求 |
16 | DefaultHttpRequest request = (DefaultHttpRequest) e.getMessage(); |
17 | if ( request.isChunked() ){ //netty自己分析文件大小,是否需要分片上传文件。 |
18 | readingChunks = true ; |
19 | } else { |
20 | ChannelBuffer buffer = request.getContent(); |
21 | readFileContent(buffer); |
22 | isUploadFinished= true ; |
23 | } |
24 | } else { //netty分片上传的实现 |
25 | HttpChunk httpChunk = (HttpChunk) e.getMessage(); |
26 | if (!httpChunk.isLast()){ |
27 | ChannelBuffer buffer = httpChunk.getContent(); |
28 | readFileContent(buffer); |
29 | } else { |
30 | readingChunks = false ; |
31 | isUploadFinished= true ; |
32 | } |
33 | } |
34 | return isUploadFinished; |
35 | } |
36 | |
37 | private boolean readFileContent( ChannelBuffer buffer ){ |
38 | try { |
39 | if (fOutputStream == null ){ |
40 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
41 | while ( buffer.readable() ){ |
42 | byte b = buffer.readByte(); |
43 | buf.write(b); |
44 | if ( b == '\n' && new String(buf.toByteArray()).endsWith( "\r\n\r\n" ) ) break ; |
45 | } |
46 | String content = buf.toString( "utf8" ); |
47 | FileItem fileItem = FileItem.parseFileItem(content); |
48 | String name = fileItem.getFieldName(); |
49 | if (!name.equals( "file" )) return false ; |
50 | String fileName = fileItem.getFilename(); |
51 | if (fileName.indexOf( "\\" ) > - 1 ) { |
52 | fileName = fileName.substring(fileName.lastIndexOf( "\\" ) + 1 ); |
53 | } |
54 | File file = new File( "D://" +fileName); |
55 | fOutputStream = new FileOutputStream(file); |
56 | } |
57 | while (buffer.readable()){ |
58 | byte [] dst = new byte [buffer.readableBytes()]; |
59 | buffer.readBytes(dst); |
60 | fOutputStream.write(dst); |
61 | } |
62 | fOutputStream.flush(); |
63 | return true ; |
64 | } catch (Exception e){ |
65 | isReadSuccess= false ; |
66 | return false ; |
67 | } |
68 | } |
69 |
70 | } |
//用于封装请求的头信息,获取文件名,文件类型等信息。
01 | class FileItem{ |
02 | private String filename; |
03 | private String mimeType; |
04 | private String fieldName; |
05 | |
06 | public FileItem( String filename , String mimeType , String fieldName ) { |
07 | this .filename = filename; |
08 | this .mimeType = mimeType; |
09 | this .fieldName = fieldName; |
10 | } |
11 | |
12 | public static FileItem parseFileItem( String content ){ |
13 | if ( content == null ) return null ; |
14 | String filename = null ; |
15 | String mimeType = null ; |
16 | String name = null ; |
17 | String[] rows = content.split( "\r\n" ); |
18 | for ( String row : rows ){ |
19 | int idx = row.indexOf( ":" ); |
20 | if ( idx > 0 ){ |
21 | String key = row.substring( 0 ,idx); |
22 | if ( "Content-Disposition" .equals(key)){ |
23 | String val = row.substring(idx+ 1 ); |
24 | String[] items = val.split( ";" ); |
25 | for ( String item : items ){ |
26 | String[] kv = item.split( "=" ); |
27 | String k = kv[ 0 ].trim(); |
28 | if ( "name" .equals(k) ){ |
29 | name = kv[ 1 ].replace( "\"" , "" ); |
30 | } else if ( "filename" .equals(k) ){ |
31 | filename = kv[ 1 ].replace( "\"" , "" ); |
32 | } |
33 | } |
34 | } else if ( "Content-Type" .equals(key) ){ |
35 | String val = row.substring(idx+ 1 ); |
36 | mimeType = val.trim(); |
37 | } |
38 | } |
39 | } |
40 | return new FileItem(filename, mimeType, name); |
41 | } |
42 | |
43 | public String getFilename() { |
44 | return filename; |
45 | } |
46 |
47 | public String getMimeType() { |
48 | return mimeType; |
49 | } |
50 |
51 | public String getFieldName() { |
52 | return fieldName; |
53 | } |
54 | |
55 | @Override |
56 | public String toString() { |
57 | return String.format( "name=%s mimetype=%s filename=%s" , this .fieldName, this .mimeType, this .filename); |
58 | } |
59 | } |