├── .idea
├── compiler.xml
├── encodings.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── libraries
│ ├── Maven__ch_qos_logback_logback_classic_1_1_11.xml
│ ├── Maven__ch_qos_logback_logback_core_1_1_11.xml
│ ├── Maven__com_fasterxml_classmate_1_3_3.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_8_9.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_8_9.xml
│ ├── Maven__com_jayway_jsonpath_json_path_2_2_0.xml
│ ├── Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
│ ├── Maven__io_netty_netty_all_4_1_21_Final.xml
│ ├── Maven__javax_validation_validation_api_1_1_0_Final.xml
│ ├── Maven__junit_junit_4_11.xml
│ ├── Maven__net_minidev_accessors_smart_1_1.xml
│ ├── Maven__net_minidev_json_smart_2_2_1.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_16.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_16.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_16.xml
│ ├── Maven__org_assertj_assertj_core_2_6_0.xml
│ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml
│ ├── Maven__org_hamcrest_hamcrest_library_1_3.xml
│ ├── Maven__org_hibernate_hibernate_validator_5_3_5_Final.xml
│ ├── Maven__org_jboss_logging_jboss_logging_3_3_1_Final.xml
│ ├── Maven__org_mockito_mockito_core_1_10_19.xml
│ ├── Maven__org_objenesis_objenesis_2_1.xml
│ ├── Maven__org_ow2_asm_asm_5_0_3.xml
│ ├── Maven__org_skyscreamer_jsonassert_1_4_0.xml
│ ├── Maven__org_slf4j_jcl_over_slf4j_1_7_25.xml
│ ├── Maven__org_slf4j_jul_to_slf4j_1_7_25.xml
│ ├── Maven__org_slf4j_log4j_over_slf4j_1_7_25.xml
│ ├── Maven__org_slf4j_slf4j_api_1_7_25.xml
│ ├── Maven__org_springframework_boot_spring_boot_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_logging_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_test_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_tomcat_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_web_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_test_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_5_6_RELEASE.xml
│ ├── Maven__org_springframework_spring_aop_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_beans_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_context_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_core_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_expression_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_test_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_web_4_3_10_RELEASE.xml
│ ├── Maven__org_springframework_spring_webmvc_4_3_10_RELEASE.xml
│ └── Maven__org_yaml_snakeyaml_1_17.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── netty-client
├── netty-client.iml
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── haoxy
│ │ │ │ └── netty
│ │ │ │ └── client
│ │ │ │ └── file
│ │ │ │ ├── ClientFileApp.java
│ │ │ │ ├── handler
│ │ │ │ └── FileUploadClientHandler.java
│ │ │ │ └── work
│ │ │ │ └── FileUploadClient.java
│ │ └── resources
│ │ │ └── application.properties
│ └── test
│ │ └── java
│ │ └── com
│ │ └── haoxy
│ │ └── netty
│ │ └── file
│ │ └── ClientFileTest.java
└── target
│ ├── classes
│ ├── application.properties
│ └── com
│ │ └── haoxy
│ │ └── netty
│ │ └── client
│ │ └── file
│ │ ├── ClientFileApp.class
│ │ ├── handler
│ │ └── FileUploadClientHandler.class
│ │ └── work
│ │ ├── FileUploadClient$1.class
│ │ └── FileUploadClient.class
│ └── test-classes
│ └── com
│ └── haoxy
│ └── netty
│ └── file
│ └── ClientFileTest.class
├── netty-common
├── netty-common.iml
├── pom.xml
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── haoxy
│ │ └── common
│ │ ├── haoxy
│ │ └── model
│ │ └── FileUploadFile.java
└── target
│ └── classes
│ └── com
│ └── haoxy
│ └── common
│ └── model
│ └── FileUploadFile.class
├── netty-file.iml
├── netty-server
├── netty-server.iml
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── haoxy
│ │ │ │ └── netty
│ │ │ │ └── server
│ │ │ │ └── file
│ │ │ │ ├── ServerFileApp.java
│ │ │ │ ├── handler
│ │ │ │ └── FileUploadServerHandler.java
│ │ │ │ └── work
│ │ │ │ └── FileUploadServer.java
│ │ └── resources
│ │ │ └── application.properties
│ └── test
│ │ └── java
│ │ └── com
│ │ └── haoxy
│ │ └── netty
│ │ └── file
│ │ └── ServerFileTest.java
└── target
│ ├── classes
│ ├── application.properties
│ └── com
│ │ └── haoxy
│ │ └── netty
│ │ └── server
│ │ └── file
│ │ ├── ServerFileApp.class
│ │ ├── handler
│ │ └── FileUploadServerHandler.class
│ │ └── work
│ │ ├── FileUploadServer$1.class
│ │ └── FileUploadServer.class
│ └── test-classes
│ └── com
│ └── haoxy
│ └── netty
│ └── file
│ └── ServerFileTest.class
└── pom.xml
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_classmate_1_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_8_9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_8_9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_netty_netty_all_4_1_21_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__junit_junit_4_11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_accessors_smart_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_json_smart_2_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_16.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_16.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_16.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_assertj_assertj_core_2_6_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_library_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hibernate_hibernate_validator_5_3_5_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_3_1_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mockito_mockito_core_1_10_19.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_objenesis_objenesis_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_ow2_asm_asm_5_0_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_4_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_25.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_25.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_log4j_over_slf4j_1_7_25.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_25.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_5_6_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_aop_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_beans_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_core_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_expression_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_test_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_web_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_webmvc_4_3_10_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_yaml_snakeyaml_1_17.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | Android > Lint > Correctness
174 |
175 |
176 | Gradle
177 |
178 |
179 | Kotlin
180 |
181 |
182 | Maven
183 |
184 |
185 | OSGi
186 |
187 |
188 | Probable bugsGradle
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 | $USER_HOME$/.subversion
400 |
401 |
402 |
403 |
404 | 1542265179376
405 |
406 |
407 | 1542265179376
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 | 1.8
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 | 1.8
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #### Netty 文件传输
2 |
3 | [2020-1-2更新](#2020-1-2更新)
4 |
5 | 在之前的项目中介绍了
6 |
7 | springboot整合 netty做心跳检测
8 |
9 | springboot 整合netty编写时间服务器
10 |
11 | 这次通过 Netty 传递文件
12 |
13 | 此项目地址: https://github.com/haoxiaoyong1014/netty-file
14 |
15 | #### 项目依赖
16 | ```xml
17 |
18 | io.netty
19 | netty-all
20 | 4.1.21.Final
21 |
22 | ```
23 | 和之前的两个例子中的依赖是一样的
24 |
25 | #### 项目中的重要部分代码
26 |
27 | * 客户端
28 |
29 | * FileUploadClientHandler
30 | ```$xslt
31 |
32 | public class FileUploadClientHandler extends ChannelInboundHandlerAdapter {
33 | private int byteRead;
34 | private volatile int start = 0;
35 | private volatile int lastLength = 0;
36 | public RandomAccessFile randomAccessFile;
37 | private FileUploadFile fileUploadFile;
38 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadClientHandler.class);
39 |
40 | public FileUploadClientHandler(FileUploadFile ef) {
41 | if (ef.getFile().exists()) {
42 | if (!ef.getFile().isFile()) {
43 | System.out.println("Not a file :" + ef.getFile());
44 | return;
45 | }
46 | }
47 | this.fileUploadFile = ef;
48 | }
49 |
50 | @Override
51 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {
52 | // TODO Auto-generated method stub
53 | super.channelInactive(ctx);
54 | LOGGER.info("客户端结束传递文件channelInactive()");
55 | }
56 |
57 | public void channelActive(ChannelHandlerContext ctx) {
58 | LOGGER.info("正在执行channelActive()方法.....");
59 | try {
60 | randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(),
61 | "r");
62 | randomAccessFile.seek(fileUploadFile.getStarPos());
63 | // lastLength = (int) randomAccessFile.length() / 10;
64 | lastLength = 1024 * 10;
65 | byte[] bytes = new byte[lastLength];
66 | if ((byteRead = randomAccessFile.read(bytes)) != -1) {
67 | fileUploadFile.setEndPos(byteRead);
68 | fileUploadFile.setBytes(bytes);
69 | ctx.writeAndFlush(fileUploadFile); //发送消息到服务端
70 | } else {
71 | }
72 | LOGGER.info("channelActive()文件已经读完 " + byteRead);
73 | } catch (FileNotFoundException e) {
74 | e.printStackTrace();
75 | } catch (IOException i) {
76 | i.printStackTrace();
77 | }
78 | LOGGER.info("channelActive()方法执行结束");
79 | }
80 |
81 | @Override
82 | public void channelRead(ChannelHandlerContext ctx, Object msg)
83 | throws Exception {
84 | if (msg instanceof Integer) {
85 | start = (Integer) msg;
86 | if (start != -1) {
87 | randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(), "r");
88 | randomAccessFile.seek(start); //将文件定位到start
89 | LOGGER.info("长度:" + (randomAccessFile.length() - start));
90 | int a = (int) (randomAccessFile.length() - start);
91 | int b = (int) (randomAccessFile.length() / 1024 * 2);
92 | if (a < lastLength) {
93 | lastLength = a;
94 | }
95 | LOGGER.info("文件长度:" + (randomAccessFile.length()) + ",start:" + start + ",a:" + a + ",b:" + b + ",lastLength:" + lastLength);
96 | byte[] bytes = new byte[lastLength];
97 | LOGGER.info("bytes的长度是="+bytes.length);
98 | if ((byteRead = randomAccessFile.read(bytes)) != -1 && (randomAccessFile.length() - start) > 0) {
99 | LOGGER.info("byteRead = " + byteRead);
100 | fileUploadFile.setEndPos(byteRead);
101 | fileUploadFile.setBytes(bytes);
102 | try {
103 | ctx.writeAndFlush(fileUploadFile);
104 | } catch (Exception e) {
105 | e.printStackTrace();
106 | }
107 | } else {
108 | randomAccessFile.close();
109 | ctx.close();
110 | LOGGER.info("文件已经读完channelRead()--------" + byteRead);
111 | }
112 | }
113 | }
114 | }
115 |
116 | }
117 | ```
118 |
119 | 这里使用了RandomAccessFile
120 |
121 | 对RandomAccessFile 做一个简单的介绍更有助于理解代码
122 |
123 | **RandomAccessFile特点**
124 |
125 | > RandomAccessFile是java Io体系中功能最丰富的文件内容访问类。即可以读取文件内容,也可以向文件中写入内容。但是和其他输入/输入流不同的是,程序可以直接跳到文件的任意位置来读写数据。
126 | 因为RandomAccessFile可以自由访问文件的任意位置,所以如果我们希望只访问文件的部分内容,那就可以使用RandomAccessFile类。
127 | 与OutputStearm,Writer等输出流不同的是,RandomAccessFile类允许自由定位文件记录指针,所以RandomAccessFile可以不从文件开始的地方进行输出,所以RandomAccessFile可以向已存在的文件后追加内容。则应该使用RandomAccessFile。
128 |
129 | > RandomAccessFile类包含了一个记录指针,用以标识当前读写处的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件记录指针位于文件头(也就是0处),
130 | 当读/写了n个字节后,文件记录指针将会向后移动n个字节。除此之外,RandomAccessFile可以自由的移动记录指针,即可以向前移动,也可以向后移动。
131 | RandomAccessFile包含了以下两个方法来操作文件的记录指针.
132 | ```$xslt
133 | long getFilePointer(); 返回文件记录指针的当前位置
134 | void seek(long pos); 将文件记录指针定位到pos位置
135 | ```
136 |
137 | > RandomAccessFile即可以读文件,也可以写,所以它即包含了完全类似于InputStream的3个read()方法,其用法和InputStream的3个read()方法完全一样;
138 | 也包含了完全类似于OutputStream的3个write()方法,其用法和OutputStream的3个Writer()方法完全一样。
139 | 除此之外,RandomAccessFile还包含了一系类的readXXX()和writeXXX()方法来完成输入和输出。
140 |
141 | - > RandomAccessFile有两个构造器,其实这两个构造器基本相同,只是指定文件的形式不同而已,一个使用String参数来指定文件名,一个使用File参数来指定文件本身。
142 | 除此之外,创建RandomAccessFile对象还需要指定一个mode参数。该参数指定RandomAccessFile的访问模式,有以下4个值:
143 |
144 | * “r” 以只读方式来打开指定文件夹。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
145 | * “rw” 以读,写方式打开指定文件。如果该文件尚不存在,则试图创建该文件。
146 | * “rws” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容或元数据的每个更新都同步写入到底层设备。
147 | * “rwd” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容每个更新都同步写入到底层设备
148 |
149 | **下面对上面的FileUploadClientHandler类中的代码进行说明:**
150 |
151 | `channelActive()`方法中有这么一段代码:
152 | ```$xslt
153 | ctx.writeAndFlush(fileUploadFile);
154 | ```
155 | 这段代码的意思是向服务端发送消息,消息内容就是`FileUploadFile`对象, FileUploadFile对象中包含 :文件,文件名,开始位置,文件字节数组,结尾位置
156 |
157 | **服务端代码:**
158 |
159 | * FileUploadServerHandler
160 | ```$xslt
161 | public class FileUploadServerHandler extends ChannelInboundHandlerAdapter {
162 | private int byteRead;
163 | private volatile int start = 0;
164 | private String file_dir = "/tmp";
165 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadServerHandler.class);
166 | @Override
167 | public void channelActive(ChannelHandlerContext ctx) throws Exception {
168 | // TODO Auto-generated method stub
169 | super.channelActive(ctx);
170 | LOGGER.info("服务端:channelActive()");
171 | }
172 |
173 | @Override
174 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {
175 | // TODO Auto-generated method stub
176 | super.channelInactive(ctx);
177 | LOGGER.info("服务端:channelInactive()");
178 | ctx.flush();
179 | ctx.close();
180 | }
181 |
182 |
183 | @Override
184 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
185 | LOGGER.info("收到客户端发来的文件,正在处理....");
186 | if (msg instanceof FileUploadFile) {
187 | FileUploadFile ef = (FileUploadFile) msg;
188 | byte[] bytes = ef.getBytes();
189 | byteRead = ef.getEndPos();
190 | String md5 = ef.getFile_md5();//文件名
191 | String path = file_dir + File.separator + md5;
192 | File file = new File(path);
193 | RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");//r: 只读模式 rw:读写模式
194 | randomAccessFile.seek(start);//移动文件记录指针的位置,
195 | randomAccessFile.write(bytes);//调用了seek(start)方法,是指把文件的记录指针定位到start字节的位置。也就是说程序将从start字节开始写数据
196 | start = start + byteRead;
197 | if (byteRead > 0) {
198 | ctx.writeAndFlush(start);//向客户端发送消息
199 | randomAccessFile.close();
200 | if(byteRead!=1024 * 10){
201 | Thread.sleep(1000);
202 | channelInactive(ctx);
203 | }
204 | } else {
205 | ctx.close();
206 | }
207 | LOGGER.info("处理完毕,文件路径:"+path+","+byteRead);
208 | }
209 | }
210 | }
211 | ```
212 |
213 | `channelRead()`方法即是接收客户端的代码,客户端也有这个方法,客户端`channelRead()`方法主要是负责读文件,服务端主要是写文件.
214 |
215 | **注意:**
216 | 在服务端`FileUploadServerHandler`这个类中我们要将`file_dir`的路径改为自己电脑上的路径,mac: /tmp; windows: F:
217 |
218 |
219 | 我们可以先运行服务端的`ServerFileTest`测试类,然后运行客户端的 `ClientFileTest`测试类进行
220 |
221 | 具体代码就不贴上去了,可以在这里进行下载这个案例
222 | netty-file
223 | 如果对你有帮助还请给个Star哦
224 |
225 |
226 | #### 2020-1-2更新
227 |
228 | 新增多个文件同时异步上传功能
229 |
230 | 引入线程,在开发中如果有此需求尽量使用线程池;
231 |
232 | 更新的代码有:
233 |
234 | ```java
235 | public class FileUploadClient implements Runnable {
236 |
237 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadClient.class);
238 |
239 | private int port;
240 | private String host;
241 | private FileUploadFile fileUploadFile;
242 |
243 |
244 | public FileUploadClient(int port, String host, FileUploadFile fileUploadFile) {
245 | this.port = port;
246 | this.host = host;
247 | this.fileUploadFile = fileUploadFile;
248 | }
249 |
250 | @Override
251 | public void run() {
252 | EventLoopGroup group = new NioEventLoopGroup();
253 | try {
254 | Bootstrap b = new Bootstrap();
255 | b.group(group).channel(NioSocketChannel.class)
256 | //是禁用nagle算法
257 | .option(ChannelOption.TCP_NODELAY, true)
258 | .handler(new ChannelInitializer() {
259 |
260 | @Override
261 | protected void initChannel(Channel ch) throws Exception {
262 | ch.pipeline().addLast(new ObjectEncoder());
263 | ch.pipeline().addLast(
264 | new ObjectDecoder(
265 | ClassResolvers
266 | .weakCachingConcurrentResolver(null)));
267 | ch.pipeline().addLast(
268 | new FileUploadClientHandler(
269 | fileUploadFile));
270 | }
271 | });
272 |
273 | ChannelFuture f = null;
274 | try {
275 | f = b.connect(host, port).sync();
276 | f.channel().closeFuture().sync();
277 | } catch (InterruptedException e) {
278 | e.printStackTrace();
279 | }
280 | LOGGER.info("FileUploadClient connect()结束");
281 | } finally {
282 | group.shutdownGracefully();
283 | }
284 | }
285 | }
286 | ```
287 | FileUploadClient类实现Runnable并重写run方法;
288 |
289 | 测试类:
290 |
291 | ```java
292 | public static void main(String[] args) {
293 | final int FILE_PORT = 9991;
294 | try {
295 | List fileNameList = new ArrayList();
296 | fileNameList.add("/test-1.zip");
297 | fileNameList.add("/test-2.zip");
298 |
299 | for (String fileName : fileNameList) {
300 | FileUploadFile uploadFile = new FileUploadFile();
301 | File file = new File(fileName);
302 | String fileMd5 = file.getName();// 文件名
303 | uploadFile.setFile(file);
304 | uploadFile.setFile_md5(fileMd5);
305 | uploadFile.setStarPos(0);// 文件开始位置
306 | Thread thread = new Thread(new FileUploadClient(FILE_PORT, "127.0.0.1", uploadFile));
307 | thread.start();
308 | System.out.println(fileName + "开始传输。。。。。。");
309 | }
310 | } catch (Exception e) {
311 | e.printStackTrace();
312 | }
313 | }
314 | ```
315 |
316 |
--------------------------------------------------------------------------------
/netty-client/netty-client.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/netty-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | netty-file
7 | com.haoxy.netty
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | netty-client
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-web
18 |
19 |
20 | org.springframework.boot
21 | spring-boot-starter-test
22 | test
23 |
24 |
25 | com.haoxy.netty
26 | netty-common
27 | v1.0
28 |
29 |
30 |
--------------------------------------------------------------------------------
/netty-client/src/main/java/com/haoxy/netty/client/file/ClientFileApp.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.client.file;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * Created by haoxy on 2018/11/15.
8 | * E-mail:hxyHelloWorld@163.com
9 | * github:https://github.com/haoxiaoyong1014
10 | */
11 | @SpringBootApplication
12 | public class ClientFileApp {
13 | public static void main(String[] args) {
14 | SpringApplication.run(ClientFileApp.class,args);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/netty-client/src/main/java/com/haoxy/netty/client/file/handler/FileUploadClientHandler.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.client.file.handler;
2 |
3 | import com.haoxy.common.model.FileUploadFile;
4 | import com.haoxy.netty.client.file.work.FileUploadClient;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.ChannelInboundHandlerAdapter;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.io.FileNotFoundException;
11 | import java.io.IOException;
12 | import java.io.RandomAccessFile;
13 | /**
14 | * Created by haoxy on 2018/11/15.
15 | * E-mail:hxyHelloWorld@163.com
16 | * github:https://github.com/haoxiaoyong1014
17 | */
18 | public class FileUploadClientHandler extends ChannelInboundHandlerAdapter {
19 | private int byteRead;
20 | private volatile int start = 0;
21 | private volatile int lastLength = 0;
22 | public RandomAccessFile randomAccessFile;
23 | private FileUploadFile fileUploadFile;
24 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadClientHandler.class);
25 | public FileUploadClientHandler(FileUploadFile ef) {
26 | if (ef.getFile().exists()) {
27 | if (!ef.getFile().isFile()) {
28 | System.out.println("Not a file :" + ef.getFile());
29 | return;
30 | }
31 | }
32 | this.fileUploadFile = ef;
33 | }
34 |
35 | @Override
36 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {
37 | // TODO Auto-generated method stub
38 | super.channelInactive(ctx);
39 | LOGGER.info("客户端结束传递文件channelInactive()");
40 | }
41 |
42 | public void channelActive(ChannelHandlerContext ctx) {
43 | LOGGER.info("正在执行channelActive()方法.....");
44 | try {
45 | randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(),
46 | "r");
47 | randomAccessFile.seek(fileUploadFile.getStarPos());
48 | // lastLength = (int) randomAccessFile.length() / 10;
49 | lastLength = 1024 * 10;
50 | byte[] bytes = new byte[lastLength];
51 | if ((byteRead = randomAccessFile.read(bytes)) != -1) {
52 | fileUploadFile.setEndPos(byteRead);
53 | fileUploadFile.setBytes(bytes);
54 | ctx.writeAndFlush(fileUploadFile);//发送消息到服务端
55 | } else {
56 | }
57 | LOGGER.info("channelActive()文件已经读完 " + byteRead);
58 | } catch (FileNotFoundException e) {
59 | e.printStackTrace();
60 | } catch (IOException i) {
61 | i.printStackTrace();
62 | }
63 | LOGGER.info("channelActive()方法执行结束");
64 | }
65 |
66 | @Override
67 | public void channelRead(ChannelHandlerContext ctx, Object msg)
68 | throws Exception {
69 | if (msg instanceof Integer) {
70 | start = (Integer) msg;
71 | if (start != -1) {
72 | randomAccessFile = new RandomAccessFile(fileUploadFile.getFile(), "r");
73 | randomAccessFile.seek(start); //将文件定位到start
74 | LOGGER.info("长度:" + (randomAccessFile.length() - start));
75 | int a = (int) (randomAccessFile.length() - start);
76 | int b = (int) (randomAccessFile.length() / 1024 * 2);
77 | if (a < lastLength) {
78 | lastLength = a;
79 | }
80 | LOGGER.info("文件长度:" + (randomAccessFile.length()) + ",start:" + start + ",a:" + a + ",b:" + b + ",lastLength:" + lastLength);
81 | byte[] bytes = new byte[lastLength];
82 | LOGGER.info("bytes的长度是="+bytes.length);
83 | if ((byteRead = randomAccessFile.read(bytes)) != -1 && (randomAccessFile.length() - start) > 0) {
84 | LOGGER.info("byteRead = " + byteRead);
85 | fileUploadFile.setEndPos(byteRead);
86 | fileUploadFile.setBytes(bytes);
87 | try {
88 | ctx.writeAndFlush(fileUploadFile);
89 | } catch (Exception e) {
90 | e.printStackTrace();
91 | }
92 | } else {
93 | randomAccessFile.close();
94 | ctx.close();
95 | LOGGER.info("文件已经读完channelRead()--------" + byteRead);
96 | }
97 | }
98 | }
99 | }
100 |
101 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
102 | cause.printStackTrace();
103 | ctx.close();
104 | }
105 |
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/netty-client/src/main/java/com/haoxy/netty/client/file/work/FileUploadClient.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.client.file.work;
2 |
3 | import com.haoxy.common.model.FileUploadFile;
4 | import com.haoxy.netty.client.file.handler.FileUploadClientHandler;
5 | import io.netty.bootstrap.Bootstrap;
6 | import io.netty.channel.*;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.nio.NioSocketChannel;
9 | import io.netty.handler.codec.serialization.ClassResolvers;
10 | import io.netty.handler.codec.serialization.ObjectDecoder;
11 | import io.netty.handler.codec.serialization.ObjectEncoder;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 |
15 | import java.io.*;
16 | /**
17 | * Created by haoxy on 2018/11/15.
18 | * E-mail:hxyHelloWorld@163.com
19 | * github:https://github.com/haoxiaoyong1014
20 | * 文件上传客户端
21 | */
22 |
23 | public class FileUploadClient {
24 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadClient.class);
25 | public void connect(int port, String host,
26 | final FileUploadFile fileUploadFile) throws Exception {
27 | EventLoopGroup group = new NioEventLoopGroup();
28 | try {
29 | Bootstrap b = new Bootstrap();
30 | b.group(group).channel(NioSocketChannel.class)
31 | .option(ChannelOption.TCP_NODELAY, true)
32 | .handler(new ChannelInitializer() {
33 |
34 | @Override
35 | protected void initChannel(Channel ch) throws Exception {
36 | ch.pipeline().addLast(new ObjectEncoder());
37 | ch.pipeline()
38 | .addLast(
39 | new ObjectDecoder(
40 | ClassResolvers
41 | .weakCachingConcurrentResolver(null)));
42 | ch.pipeline()
43 | .addLast(
44 | new FileUploadClientHandler(
45 | fileUploadFile));
46 | }
47 | });
48 | ChannelFuture f = b.connect(host, port).sync();
49 | f.channel().closeFuture().sync();
50 | LOGGER.info("FileUploadClient connect()结束");
51 | } finally {
52 | group.shutdownGracefully();
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/netty-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # web port
2 | server.port=8084
3 |
4 | netty.client.host=127.0.0.1
5 | netty.client.port=9991
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/netty-client/src/test/java/com/haoxy/netty/file/ClientFileTest.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.file;
2 |
3 | import com.haoxy.common.model.FileUploadFile;
4 | import com.haoxy.netty.client.file.work.FileUploadClient;
5 | import org.junit.Test;
6 |
7 |
8 | import java.io.File;
9 |
10 | /**
11 | * Created by haoxy on 2018/11/15.
12 | * E-mail:hxyHelloWorld@163.com
13 | * github:https://github.com/haoxiaoyong1014
14 | */
15 | public class ClientFileTest {
16 | private static final int FILE_PORT = 9991;
17 | @Test
18 | public void testFile(){
19 | try {
20 | FileUploadFile uploadFile = new FileUploadFile();
21 | File file = new File("/Users/haoxiaoyong/Desktop/幸运大转盘活动协议书.docx");//
22 | String fileMd5 = file.getName();// 文件名
23 | uploadFile.setFile(file);
24 | uploadFile.setFile_md5(fileMd5);
25 | uploadFile.setStarPos(0);// 文件开始位置
26 | new FileUploadClient().connect(FILE_PORT, "127.0.0.1", uploadFile);
27 | } catch (Exception e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/netty-client/target/classes/application.properties:
--------------------------------------------------------------------------------
1 | # web port
2 | server.port=8084
3 |
4 | netty.client.host=127.0.0.1
5 | netty.client.port=9991
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/netty-client/target/classes/com/haoxy/netty/client/file/ClientFileApp.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-client/target/classes/com/haoxy/netty/client/file/ClientFileApp.class
--------------------------------------------------------------------------------
/netty-client/target/classes/com/haoxy/netty/client/file/handler/FileUploadClientHandler.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-client/target/classes/com/haoxy/netty/client/file/handler/FileUploadClientHandler.class
--------------------------------------------------------------------------------
/netty-client/target/classes/com/haoxy/netty/client/file/work/FileUploadClient$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-client/target/classes/com/haoxy/netty/client/file/work/FileUploadClient$1.class
--------------------------------------------------------------------------------
/netty-client/target/classes/com/haoxy/netty/client/file/work/FileUploadClient.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-client/target/classes/com/haoxy/netty/client/file/work/FileUploadClient.class
--------------------------------------------------------------------------------
/netty-client/target/test-classes/com/haoxy/netty/file/ClientFileTest.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-client/target/test-classes/com/haoxy/netty/file/ClientFileTest.class
--------------------------------------------------------------------------------
/netty-common/netty-common.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/netty-common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | netty-file
7 | com.haoxy.netty
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | com.haoxy.netty
12 | netty-common
13 | v1.0
14 |
15 |
16 |
--------------------------------------------------------------------------------
/netty-common/src/main/java/com/haoxy/common/haoxy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-common/src/main/java/com/haoxy/common/haoxy
--------------------------------------------------------------------------------
/netty-common/src/main/java/com/haoxy/common/model/FileUploadFile.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.common.model;
2 |
3 | import java.io.File;
4 | import java.io.Serializable;
5 |
6 | /**
7 | * Created by haoxy on 2018/11/15.
8 | * E-mail:hxyHelloWorld@163.com
9 | * github:https://github.com/haoxiaoyong1014
10 | */
11 | public class FileUploadFile implements Serializable {
12 |
13 | private static final long serialVersionUID = 1L;
14 | private File file;// 文件
15 | private String file_md5;// 文件名
16 | private int starPos;// 开始位置
17 | private byte[] bytes;// 文件字节数组
18 | private int endPos;// 结尾位置
19 |
20 | public File getFile() {
21 | return file;
22 | }
23 |
24 | public void setFile(File file) {
25 | this.file = file;
26 | }
27 |
28 | public String getFile_md5() {
29 | return file_md5;
30 | }
31 |
32 | public void setFile_md5(String file_md5) {
33 | this.file_md5 = file_md5;
34 | }
35 |
36 | public int getStarPos() {
37 | return starPos;
38 | }
39 |
40 | public void setStarPos(int starPos) {
41 | this.starPos = starPos;
42 | }
43 |
44 | public byte[] getBytes() {
45 | return bytes;
46 | }
47 |
48 | public void setBytes(byte[] bytes) {
49 | this.bytes = bytes;
50 | }
51 |
52 | public int getEndPos() {
53 | return endPos;
54 | }
55 |
56 | public void setEndPos(int endPos) {
57 | this.endPos = endPos;
58 | }
59 |
60 | public static long getSerialversionuid() {
61 | return serialVersionUID;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/netty-common/target/classes/com/haoxy/common/model/FileUploadFile.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-common/target/classes/com/haoxy/common/model/FileUploadFile.class
--------------------------------------------------------------------------------
/netty-file.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/netty-server/netty-server.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/netty-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | netty-file
7 | com.haoxy.netty
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | netty-server
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-web
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-starter-test
21 | test
22 |
23 |
24 | com.haoxy.netty
25 | netty-common
26 | v1.0
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/netty-server/src/main/java/com/haoxy/netty/server/file/ServerFileApp.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.server.file;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * Created by haoxy on 2018/11/15.
8 | * E-mail:hxyHelloWorld@163.com
9 | * github:https://github.com/haoxiaoyong1014
10 | */
11 | @SpringBootApplication
12 | public class ServerFileApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(ServerFileApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/netty-server/src/main/java/com/haoxy/netty/server/file/handler/FileUploadServerHandler.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.server.file.handler;
2 |
3 | import com.haoxy.common.model.FileUploadFile;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.io.File;
10 | import java.io.RandomAccessFile;
11 | /**
12 | * Created by haoxy on 2018/11/15.
13 | * E-mail:hxyHelloWorld@163.com
14 | * github:https://github.com/haoxiaoyong1014
15 | */
16 | public class FileUploadServerHandler extends ChannelInboundHandlerAdapter {
17 | private int byteRead;
18 | private volatile int start = 0;
19 | private String file_dir = "/tmp";
20 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadServerHandler.class);
21 | @Override
22 | public void channelActive(ChannelHandlerContext ctx) throws Exception {
23 | // TODO Auto-generated method stub
24 | super.channelActive(ctx);
25 | LOGGER.info("服务端:channelActive()");
26 | }
27 |
28 | @Override
29 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {
30 | // TODO Auto-generated method stub
31 | super.channelInactive(ctx);
32 | LOGGER.info("服务端:channelInactive()");
33 | ctx.flush();
34 | ctx.close();
35 | }
36 |
37 |
38 | @Override
39 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
40 | LOGGER.info("收到客户端发来的文件,正在处理....");
41 | if (msg instanceof FileUploadFile) {
42 | FileUploadFile ef = (FileUploadFile) msg;
43 | byte[] bytes = ef.getBytes();
44 | byteRead = ef.getEndPos();
45 | String md5 = ef.getFile_md5();//文件名
46 | String path = file_dir + File.separator + md5;
47 | File file = new File(path);
48 | RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");//r: 只读模式 rw:读写模式
49 | randomAccessFile.seek(start);//移动文件记录指针的位置,
50 | randomAccessFile.write(bytes);//调用了seek(start)方法,是指把文件的记录指针定位到start字节的位置。也就是说程序将从start字节开始写数据
51 | start = start + byteRead;
52 | if (byteRead > 0) {
53 | ctx.writeAndFlush(start);//向客户端发送消息
54 | randomAccessFile.close();
55 | if(byteRead!=1024 * 10){
56 | Thread.sleep(1000);
57 | channelInactive(ctx);
58 | }
59 | } else {
60 | ctx.close();
61 | }
62 | LOGGER.info("处理完毕,文件路径:"+path+","+byteRead);
63 | }
64 | }
65 |
66 | @Override
67 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
68 | cause.printStackTrace();
69 | ctx.close();
70 | LOGGER.info("FileUploadServerHandler--exceptionCaught()");
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/netty-server/src/main/java/com/haoxy/netty/server/file/work/FileUploadServer.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.server.file.work;
2 |
3 | import com.haoxy.netty.server.file.handler.FileUploadServerHandler;
4 | import io.netty.bootstrap.ServerBootstrap;
5 | import io.netty.channel.*;
6 | import io.netty.channel.nio.NioEventLoopGroup;
7 | import io.netty.channel.socket.nio.NioServerSocketChannel;
8 | import io.netty.handler.codec.serialization.ClassResolvers;
9 | import io.netty.handler.codec.serialization.ObjectDecoder;
10 | import io.netty.handler.codec.serialization.ObjectEncoder;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | /**
15 | * Created by haoxy on 2018/11/15.
16 | * E-mail:hxyHelloWorld@163.com
17 | * github:https://github.com/haoxiaoyong1014
18 | * 文件上传服务端
19 | */
20 | public class FileUploadServer {
21 | private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadServer.class);
22 | public void bind(int port) throws Exception {
23 | EventLoopGroup bossGroup = new NioEventLoopGroup();
24 | EventLoopGroup workerGroup = new NioEventLoopGroup();
25 | try {
26 | ServerBootstrap b = new ServerBootstrap();
27 | b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChannelInitializer() {
28 |
29 | @Override
30 | protected void initChannel(Channel ch) throws Exception {
31 | LOGGER.info("有客户端连接上来:"+ch.localAddress().toString());
32 | ch.pipeline().addLast(new ObjectEncoder());
33 | ch.pipeline().addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.weakCachingConcurrentResolver(null))); // 最大长度
34 | ch.pipeline().addLast(new FileUploadServerHandler());
35 | }
36 | });
37 | ChannelFuture f = b.bind(port).sync();
38 | LOGGER.info("file server 等待连接:");
39 | f.channel().closeFuture().sync();
40 | LOGGER.info("file end");
41 | } finally {
42 | bossGroup.shutdownGracefully();
43 | workerGroup.shutdownGracefully();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/netty-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # web port
2 | server.port=8083
3 |
4 | netty.server.host=127.0.0.1
5 | netty.server.port=9991
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/netty-server/src/test/java/com/haoxy/netty/file/ServerFileTest.java:
--------------------------------------------------------------------------------
1 | package com.haoxy.netty.file;
2 |
3 | import com.haoxy.netty.server.file.work.FileUploadServer;
4 | import org.junit.Test;
5 |
6 | /**
7 | * Created by haoxy on 2018/11/15.
8 | * E-mail:hxyHelloWorld@163.com
9 | * github:https://github.com/haoxiaoyong1014
10 | */
11 | public class ServerFileTest {
12 |
13 | private static final int FILE_PORT = 9991;
14 |
15 | @Test
16 | public void testServerFile() {
17 | try {
18 | new FileUploadServer().bind(FILE_PORT);
19 | } catch (Exception e) {
20 | e.printStackTrace();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/netty-server/target/classes/application.properties:
--------------------------------------------------------------------------------
1 | # web port
2 | server.port=8083
3 |
4 | netty.server.host=127.0.0.1
5 | netty.server.port=9991
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/netty-server/target/classes/com/haoxy/netty/server/file/ServerFileApp.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-server/target/classes/com/haoxy/netty/server/file/ServerFileApp.class
--------------------------------------------------------------------------------
/netty-server/target/classes/com/haoxy/netty/server/file/handler/FileUploadServerHandler.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-server/target/classes/com/haoxy/netty/server/file/handler/FileUploadServerHandler.class
--------------------------------------------------------------------------------
/netty-server/target/classes/com/haoxy/netty/server/file/work/FileUploadServer$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-server/target/classes/com/haoxy/netty/server/file/work/FileUploadServer$1.class
--------------------------------------------------------------------------------
/netty-server/target/classes/com/haoxy/netty/server/file/work/FileUploadServer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-server/target/classes/com/haoxy/netty/server/file/work/FileUploadServer.class
--------------------------------------------------------------------------------
/netty-server/target/test-classes/com/haoxy/netty/file/ServerFileTest.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haoxiaoyong1014/netty-file/10d46fa72aa28a9efe95ffc7b344ae7e5182f4fc/netty-server/target/test-classes/com/haoxy/netty/file/ServerFileTest.class
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | pom
7 |
8 | netty-client
9 | netty-server
10 | netty-common
11 |
12 |
13 | org.springframework.boot
14 | spring-boot-starter-parent
15 | 1.5.6.RELEASE
16 |
17 |
18 |
19 | com.haoxy.netty
20 | netty-file
21 | 1.0-SNAPSHOT
22 |
23 | 4.11
24 | 4.1.42.Final
25 | UTF-8
26 | UTF-8
27 |
28 |
29 |
30 | io.netty
31 | netty-all
32 | 4.1.42.Final
33 |
34 |
35 |
36 | junit
37 | junit
38 | ${junit.version}
39 |
40 |
41 |
--------------------------------------------------------------------------------