├── .classpath
├── .gitignore
├── .project
├── .settings
├── org.eclipse.jdt.core.prefs
├── org.eclipse.jdt.ui.prefs
├── org.eclipse.m2e.core.prefs
└── org.eclipse.wst.common.project.facet.core.xml
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── cn
│ │ └── clxy
│ │ └── upload
│ │ ├── ApacheHCUploader.java
│ │ ├── Config.java
│ │ ├── Listener.java
│ │ ├── Part.java
│ │ ├── UploadFileService.java
│ │ └── Uploader.java
└── resources
│ ├── bigFileUpload.properties
│ └── commons-logging.properties
└── test
└── java
└── cn
└── clxy
└── upload
└── UploadFileServiceTest.java
/.classpath:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | # Package Files #
3 | *.jar
4 | *.war
5 | *.ear
6 | target/
7 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | BigFileUploadJava
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.common.project.facet.core.builder
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.m2e.core.maven2Builder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.jdt.core.javanature
26 | org.eclipse.m2e.core.maven2Nature
27 | org.eclipse.wst.common.project.facet.core.nature
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.6
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
12 | org.eclipse.jdt.core.compiler.source=1.6
13 | org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
14 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
15 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
16 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
17 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
18 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
19 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
20 | org.eclipse.jdt.core.formatter.alignment_for_assignment=0
21 | org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
22 | org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
23 | org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
24 | org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
25 | org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
26 | org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
27 | org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
28 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
29 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
30 | org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
31 | org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
32 | org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
33 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
34 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
35 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
36 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
37 | org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
38 | org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
39 | org.eclipse.jdt.core.formatter.blank_lines_after_package=1
40 | org.eclipse.jdt.core.formatter.blank_lines_before_field=0
41 | org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
42 | org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
43 | org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
44 | org.eclipse.jdt.core.formatter.blank_lines_before_method=1
45 | org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
46 | org.eclipse.jdt.core.formatter.blank_lines_before_package=0
47 | org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
48 | org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
49 | org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
50 | org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
51 | org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
52 | org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
53 | org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
54 | org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
55 | org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
56 | org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
57 | org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
58 | org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
59 | org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
60 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
61 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
62 | org.eclipse.jdt.core.formatter.comment.format_block_comments=true
63 | org.eclipse.jdt.core.formatter.comment.format_header=false
64 | org.eclipse.jdt.core.formatter.comment.format_html=true
65 | org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
66 | org.eclipse.jdt.core.formatter.comment.format_line_comments=true
67 | org.eclipse.jdt.core.formatter.comment.format_source_code=true
68 | org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
69 | org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
70 | org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
71 | org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
72 | org.eclipse.jdt.core.formatter.comment.line_length=100
73 | org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
74 | org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
75 | org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
76 | org.eclipse.jdt.core.formatter.compact_else_if=true
77 | org.eclipse.jdt.core.formatter.continuation_indentation=2
78 | org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
79 | org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
80 | org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
81 | org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
82 | org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
83 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
84 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
85 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
86 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
87 | org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
88 | org.eclipse.jdt.core.formatter.indent_empty_lines=false
89 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
90 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
91 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
92 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
93 | org.eclipse.jdt.core.formatter.indentation.size=4
94 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
95 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
96 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
97 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
98 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
99 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
100 | org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
101 | org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
102 | org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
103 | org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
104 | org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
105 | org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
106 | org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
107 | org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
108 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
109 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
110 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
111 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
112 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
113 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
114 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
115 | org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
116 | org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
117 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
118 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
119 | org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
120 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
121 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
122 | org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
123 | org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
124 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
125 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
126 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
127 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
128 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
129 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
130 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
131 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
132 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
133 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
134 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
135 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
136 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
137 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
138 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
139 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
140 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
141 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
142 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
143 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
144 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
145 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
146 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
147 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
148 | org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
149 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
150 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
151 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
152 | org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
153 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
154 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
155 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
156 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
157 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
158 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
159 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
160 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
161 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
162 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
163 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
164 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
165 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
166 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
167 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
168 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
169 | org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
170 | org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
171 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
172 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
173 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
174 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
175 | org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
176 | org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
177 | org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
178 | org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
179 | org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
180 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
181 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
182 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
183 | org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
184 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
185 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
186 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
187 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
188 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
189 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
190 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
191 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
192 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
193 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
194 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
195 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
196 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
197 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
198 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
199 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
200 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
201 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
202 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
203 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
204 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
205 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
206 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
207 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
208 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
209 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
210 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
211 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
212 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
213 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
214 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
215 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
216 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
217 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
218 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
219 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
220 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
221 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
222 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
223 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
224 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
225 | org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
226 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
227 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
228 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
229 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
230 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
231 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
232 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
233 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
234 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
235 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
236 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
237 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
238 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
239 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
240 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
241 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
242 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
243 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
244 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
245 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
246 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
247 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
248 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
249 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
250 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
251 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
252 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
253 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
254 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
255 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
256 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
257 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
258 | org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
259 | org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
260 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
261 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
262 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
263 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
264 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
265 | org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
266 | org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
267 | org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
268 | org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
269 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
270 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
271 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
272 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
273 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
274 | org.eclipse.jdt.core.formatter.join_lines_in_comments=true
275 | org.eclipse.jdt.core.formatter.join_wrapped_lines=false
276 | org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
277 | org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
278 | org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
279 | org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
280 | org.eclipse.jdt.core.formatter.lineSplit=100
281 | org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
282 | org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
283 | org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
284 | org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
285 | org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
286 | org.eclipse.jdt.core.formatter.tabulation.char=tab
287 | org.eclipse.jdt.core.formatter.tabulation.size=4
288 | org.eclipse.jdt.core.formatter.use_on_off_tags=false
289 | org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
290 | org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
291 | org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
292 | org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
293 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.ui.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | formatter_profile=_Clxy
3 | formatter_settings_version=12
4 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 clxy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | BigFileUploadJava
2 | ====================
3 |
4 | ### [☆ English](#english) ###
5 | ### [☆ 中文](#chinese) ###
6 |
7 | Basics
8 | -----------------------------------
9 | Upload big file using java.
10 |
11 | ### Process Flow
12 | Basically, read a big file into small parts and upload. When all file parts upload is complete, combine at server.
13 |
14 | #### Client
15 |
16 | 1. Read the big file into several small parts. Considering I/O contention, use just one thread; Considering memory usage, read file part by part into fixed size queue.
17 | 2. Upload every readed file part. Usually multiple threads would be better, but can't too much, default threads count is 5.
18 | 3. After all parts uploaded, notify server to combine.
19 | 4. Can retry the specific parts only if failed to process.
20 |
21 | #### Server
22 |
23 | 1. Save recieved file parts.
24 | 2. Combine all parts by notification.
25 |
26 | #### Others
27 |
28 | - Producer/Consumer pattern.
29 | - Communicate read and upload processes by BlockingQueue.
30 | - Uploading is using Apache HttpComponents currently. There can be other implementations.
31 | - Can be used in the android. Please refer to [BigFileUploadAndroid](https://github.com/clxy/BigFileUploadAndroid)。
32 |
33 |
34 | ### Usage
35 |
36 | #### Configuration
37 | Please refer to [cn.clxy.upload.Config](https://github.com/clxy/BigFileUploadJava/blob/master/src/main/java/cn/clxy/upload/Config.java).
38 |
39 | Please note that the maximum memory usage might be:
40 | ```PART_SIZE * (MAX_UPLOAD + MAX_READ - 1)```
41 |
42 | #### Upload
43 | UploadFileService service = new UploadFileService(yourFileName);
44 | service.upload();
45 |
46 | #### Retry failed parts
47 | UploadFileService service = new UploadFileService(yourFileName);
48 | service.retry(1, 2);
49 |
50 | ### Server
51 | Because it is via HTTP, so it can be in any language, such as Java, PHP, Python, etc.
52 | Here is a java example.
53 |
54 | ```Java
55 | ...
56 | try (FileOutputStream dest = new FileOutputStream(destFile, true)) {
57 |
58 | FileChannel dc = dest.getChannel();// the final big file.
59 | for (long i = 0; i < count; i++) {
60 | File partFile = new File(destFileName + "." + i);// every small parts.
61 | if (!partFile.exists()) {
62 | break;
63 | }
64 | try (FileInputStream part = new FileInputStream(partFile)) {
65 | FileChannel pc = part.getChannel();
66 | pc.transferTo(0, pc.size(), dc);// combine.
67 | }
68 | partFile.delete();
69 | }
70 | statusCode = OK;// set ok at last.
71 | } catch (Exception e) {
72 | log.error("combine failed.", e);
73 | }
74 | ```
75 |
76 | * * ** * ** * ** * ** * ** * ** * ** * ** * *
77 |
78 |
79 | 概要
80 | -----------------------------------
81 | 使用Java上传大文件的实现。
82 |
83 | ### 处理流程
84 | 基本上是将大文件拆成小块,读取,上传。当所有文件块上传完成后,合并。
85 |
86 | #### 客户端
87 |
88 | 1. 读取文件到小的文件块。考虑到I/O竞争只用单线程;考虑到内存消耗采取分批读取。
89 | 2. 将读取的文件块上传。通常多个线程会好些,但是太多又不行,默认用5线程上传。
90 | 3. 所有文件块全部上传后,通知服务器合并。
91 | 4. 如果有部分文件块处理失败,可以重试失败部分。
92 |
93 | #### 服务器
94 |
95 | 1. 收到文件块后直接保存。
96 | 2. 收到通知后合并所有文件块。
97 |
98 | #### 其他
99 |
100 | - 使用生产/消费者模式。
101 | - 读取和上传的通信使用BlockingQueue。
102 | - 目前上传用Apache HttpComponents。可以有其他实现。
103 | - 可以用在Android上。请参考[BigFileUploadAndroid](https://github.com/clxy/BigFileUploadAndroid)。
104 |
105 |
106 | ### 使用
107 |
108 | #### 配置
109 | 请参考 [cn.clxy.upload.Config](https://github.com/clxy/BigFileUploadJava/blob/master/src/main/java/cn/clxy/upload/Config.java).
110 |
111 | 请注意内存的最大使用量可能是:
112 | ```PART_SIZE * (MAX_UPLOAD + MAX_READ - 1)```
113 |
114 | #### 上传
115 | UploadFileService service = new UploadFileService(yourFileName);
116 | service.upload();
117 |
118 | #### 重试失败部分
119 | UploadFileService service = new UploadFileService(yourFileName);
120 | service.retry(1, 2);
121 |
122 | ### 服务器
123 | 由于是经由HTTP上传,所以可以是任何语言如Java,PHP,Python等。
124 | 下面是合并文件的Java实例。
125 |
126 | ```Java
127 | ...
128 | try (FileOutputStream dest = new FileOutputStream(destFile, true)) {
129 |
130 | FileChannel dc = dest.getChannel();// 最终的大文件。
131 | for (long i = 0; i < count; i++) {
132 | File partFile = new File(destFileName + "." + i);// 每个文件块。
133 | if (!partFile.exists()) {
134 | break;
135 | }
136 | try (FileInputStream part = new FileInputStream(partFile)) {
137 | FileChannel pc = part.getChannel();
138 | pc.transferTo(0, pc.size(), dc);// 合并。
139 | }
140 | partFile.delete();
141 | }
142 | statusCode = OK;// 最终设状态OK。
143 | } catch (Exception e) {
144 | log.error("combine failed.", e);
145 | }
146 | ```
147 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | BigFileUploadJava
5 | BigFileUploadJava
6 | 0.0.1
7 | Upload big file by java. Using Apache HttpComponents. Can work on Android too.
8 |
9 |
10 | 4.3.6
11 |
12 |
13 |
14 | commons-codec
15 | commons-codec
16 | 1.8
17 |
18 |
19 | org.apache.httpcomponents
20 | httpclient
21 | ${httpcomponents}
22 | compile
23 |
24 |
25 | org.apache.httpcomponents
26 | httpmime
27 | ${httpcomponents}
28 | compile
29 |
30 |
31 | org.apache.httpcomponents
32 | httpclient-cache
33 | ${httpcomponents}
34 | compile
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/ApacheHCUploader.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | import java.io.UnsupportedEncodingException;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 | import java.util.Map.Entry;
12 |
13 | import org.apache.commons.logging.Log;
14 | import org.apache.commons.logging.LogFactory;
15 | import org.apache.http.HttpResponse;
16 | import org.apache.http.HttpStatus;
17 | import org.apache.http.client.HttpClient;
18 | import org.apache.http.client.methods.HttpPost;
19 | import org.apache.http.conn.scheme.PlainSocketFactory;
20 | import org.apache.http.conn.scheme.Scheme;
21 | import org.apache.http.conn.scheme.SchemeRegistry;
22 | import org.apache.http.conn.ssl.SSLSocketFactory;
23 | import org.apache.http.entity.mime.MultipartEntity;
24 | import org.apache.http.entity.mime.content.ByteArrayBody;
25 | import org.apache.http.entity.mime.content.ContentBody;
26 | import org.apache.http.entity.mime.content.StringBody;
27 | import org.apache.http.impl.client.DefaultHttpClient;
28 | import org.apache.http.impl.conn.PoolingClientConnectionManager;
29 | import org.apache.http.params.BasicHttpParams;
30 | import org.apache.http.params.HttpConnectionParams;
31 | import org.apache.http.params.HttpParams;
32 |
33 | /**
34 | * Use http client to upload.
35 | * @author clxy
36 | */
37 | public class ApacheHCUploader implements Uploader {
38 |
39 | private static HttpClient client = createClient();
40 | private static final Log log = LogFactory.getLog(ApacheHCUploader.class);
41 |
42 | @Override
43 | public void upload(Part part) {
44 |
45 | String partName = part.getName();
46 | Map params = new HashMap();
47 | params.put(Config.keyFile, new ByteArrayBody(part.getContent(), partName));
48 | post(params);
49 | log.debug(partName + " uploaded.");
50 | }
51 |
52 | @Override
53 | public void done(String fileName, long partCount) {
54 |
55 | Map params = new HashMap();
56 | try {
57 | params.put(Config.keyFileName, new StringBody(fileName));
58 | params.put(Config.keyPartCount, new StringBody(String.valueOf(partCount)));
59 | } catch (UnsupportedEncodingException e) {
60 | throw new RuntimeException(e);
61 | }
62 |
63 | post(params);
64 | log.debug(fileName + " notification is done.");
65 | }
66 |
67 | private void post(Map params) {
68 |
69 | HttpPost post = new HttpPost(Config.url);
70 | MultipartEntity entity = new MultipartEntity();
71 | for (Entry e : params.entrySet()) {
72 | entity.addPart(e.getKey(), e.getValue());
73 | }
74 | post.setEntity(entity);
75 |
76 | try {
77 | HttpResponse response = client.execute(post);
78 | int statusCode = response.getStatusLine().getStatusCode();
79 | if (statusCode != HttpStatus.SC_OK) {
80 | throw new RuntimeException("Upload failed.");
81 | }
82 | } catch (Exception e) {
83 | post.abort();
84 | throw new RuntimeException(e);
85 | } finally {
86 | post.releaseConnection();
87 | }
88 | }
89 |
90 | /**
91 | * The timeout should be adjusted by network condition.
92 | * @return
93 | */
94 | private static HttpClient createClient() {
95 |
96 | SchemeRegistry schReg = new SchemeRegistry();
97 | schReg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
98 | schReg.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
99 |
100 | PoolingClientConnectionManager ccm = new PoolingClientConnectionManager(schReg);
101 | ccm.setMaxTotal(Config.maxUpload);
102 |
103 | HttpParams params = new BasicHttpParams();
104 | HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
105 | HttpConnectionParams.setSoTimeout(params, Config.timeOut);
106 |
107 | return new DefaultHttpClient(ccm, params);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/Config.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | import java.io.InputStream;
9 | import java.util.Properties;
10 |
11 | public class Config {
12 |
13 | public static String url = "http://192.168.1.99:8080/ssm/common/upload";
14 |
15 | // Keys used by server.
16 | public static String keyFile = "file";
17 | public static String keyFileName = "fileName";
18 | public static String keyPartCount = "partCount";
19 |
20 | // Upload threads and timeout per thread. Should be adjusted by network condition.
21 | public static int maxUpload = 5;
22 | public static int timeOut = 120 * 1000;
23 |
24 | // The size of part.
25 | public static int partSize = 100 * 1024;
26 | public static int maxRead = 5;
27 |
28 | static {
29 | // load properties
30 | ClassLoader cl = Thread.currentThread().getContextClassLoader();
31 | try {
32 | InputStream is = cl.getResourceAsStream("bigFileUpload.properties");
33 | if (is != null) {
34 | Properties p = new Properties();
35 | p.load(is);
36 | url = p.getProperty("url");
37 | keyFile = p.getProperty("keyFile");
38 | keyFileName = p.getProperty("keyFileName");
39 | keyPartCount = p.getProperty("keyPartCount");
40 |
41 | String s = p.getProperty("maxUpload");
42 | maxUpload = Integer.parseInt(s);
43 | s = p.getProperty("timeOut");
44 | timeOut = Integer.parseInt(s) * 1000;
45 | s = p.getProperty("partSize");
46 | partSize = Integer.parseInt(s) * 1024;
47 | s = p.getProperty("maxRead");
48 | maxRead = Integer.parseInt(s);
49 |
50 | }
51 | } catch (Exception e) {
52 | // do nothing.
53 | }
54 | }
55 |
56 | private Config() {
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/Listener.java:
--------------------------------------------------------------------------------
1 | package cn.clxy.upload;
2 |
3 | public interface Listener {
4 |
5 | void onStart(Object info);
6 |
7 | void onRead(Object info);
8 |
9 | void onUpload(Object info);
10 |
11 | void onPartDone(Object info);
12 |
13 | void onNotify();
14 |
15 | void onFail(Object info);
16 |
17 | void onSuccess();
18 |
19 | public static class Default implements Listener {
20 |
21 | @Override
22 | public void onStart(Object info) {
23 | onMessage("Start uploading " + info + " part(s).");
24 | }
25 |
26 | @Override
27 | public void onRead(Object info) {
28 | onMessage("Reading part " + info + ".");
29 | }
30 |
31 | @Override
32 | public void onUpload(Object info) {
33 | onMessage("Uploading part " + info + ".");
34 | }
35 |
36 | @Override
37 | public void onPartDone(Object info) {
38 | onMessage("Part " + info + " is done.");
39 | }
40 |
41 | @Override
42 | public void onNotify() {
43 | onMessage("Notifying.");
44 | }
45 |
46 | @Override
47 | public void onFail(Object info) {
48 | onMessage(info + " failed.");
49 | }
50 |
51 | @Override
52 | public void onSuccess() {
53 | onMessage("Success.");
54 | }
55 |
56 | protected void onMessage(String msg) {
57 | System.out.println(msg);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/Part.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | public class Part {
9 |
10 | private byte[] content;
11 | private String name;
12 | public static final Part NULL = new Part();
13 |
14 | public Part() {
15 | this(null, null);
16 | }
17 |
18 | public Part(String name, byte[] content) {
19 | this.content = content;
20 | this.name = name;
21 | }
22 |
23 | public byte[] getContent() {
24 | return content;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/UploadFileService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | import java.io.File;
9 | import java.io.FileInputStream;
10 | import java.nio.ByteBuffer;
11 | import java.nio.channels.FileChannel;
12 | import java.util.Arrays;
13 | import java.util.Collections;
14 | import java.util.List;
15 | import java.util.concurrent.ArrayBlockingQueue;
16 | import java.util.concurrent.BlockingQueue;
17 | import java.util.concurrent.Callable;
18 | import java.util.concurrent.CompletionService;
19 | import java.util.concurrent.ExecutionException;
20 | import java.util.concurrent.ExecutorCompletionService;
21 | import java.util.concurrent.ExecutorService;
22 | import java.util.concurrent.Executors;
23 | import java.util.concurrent.Future;
24 |
25 | import org.apache.commons.logging.Log;
26 | import org.apache.commons.logging.LogFactory;
27 |
28 | public class UploadFileService {
29 |
30 | private File file;
31 | private BlockingQueue parts;
32 | private List indexes;
33 |
34 | private Listener listener = new Listener.Default();
35 | private Uploader uploader = new ApacheHCUploader();
36 | private ExecutorService executor = Executors.newFixedThreadPool(Config.maxUpload);
37 |
38 | private static final Log log = LogFactory.getLog(UploadFileService.class);
39 |
40 | public UploadFileService(String fileName) {
41 | file = new File(fileName);
42 | if (!file.exists() || !file.isFile()) {
43 | throw new RuntimeException("File:" + file + " isn't correct!");
44 | }
45 | }
46 |
47 | public void upload() {
48 | try {
49 | doUpload();
50 | } finally {
51 | stop();
52 | }
53 | }
54 |
55 | public void retry(Integer... array) {
56 |
57 | // sort first.
58 | indexes = Arrays.asList(array);
59 | Collections.sort(indexes);
60 |
61 | try {
62 | doUpload();
63 | } finally {
64 | stop();
65 | }
66 | }
67 |
68 | public void stop() {
69 | if (executor != null) {
70 | executor.shutdown();
71 | }
72 | }
73 |
74 | private void doUpload() {
75 |
76 | listener.onStart(indexes != null ? indexes.size() : getPartCount());
77 | parts = new ArrayBlockingQueue(Config.maxRead);
78 | CompletionService cs = new ExecutorCompletionService(executor);
79 |
80 | cs.submit(readTask);
81 |
82 | for (int i = 0; i < Config.maxUpload; i++) {
83 | cs.submit(new UploadTask("upload." + i));
84 | }
85 |
86 | // Wait all done. total count = maxUpload + 1.
87 | for (int i = 0; i <= Config.maxUpload; i++) {
88 | Future future = null;
89 | try {
90 | future = cs.take();
91 | checkFuture(future);
92 | } catch (InterruptedException e) {
93 | Thread.currentThread().interrupt();
94 | }
95 | }
96 |
97 | // Notify sever all done.
98 | Future result = executor.submit(notifyTask);
99 | checkFuture(result);
100 | listener.onSuccess();
101 | }
102 |
103 | private String checkFuture(Future future) {
104 |
105 | String result = null;
106 | try {
107 | result = future.get();
108 | return result;
109 | } catch (InterruptedException e) {
110 | Thread.currentThread().interrupt();
111 | return null;
112 | } catch (ExecutionException e) {
113 | listener.onFail(result);
114 | log.error(e.getCause());
115 | throw new RuntimeException(e.getCause());
116 | }
117 | }
118 |
119 | protected int getPartCount() {
120 | long length = file.length();
121 | long count = (length / Config.partSize) + (length % Config.partSize == 0 ? 0 : 1);
122 | return (int) count;
123 | }
124 |
125 | private Callable readTask = new Callable() {
126 |
127 | @Override
128 | public String call() throws Exception {
129 |
130 | FileInputStream fis = null;
131 | String fileName = file.getName();
132 | int partSize = Config.partSize;
133 |
134 | try {
135 | fis = new FileInputStream(file);
136 | FileChannel fc = fis.getChannel();
137 | for (int i = 0;; i++) {
138 | ReadStatus status = getReadStatus(i, indexes);
139 | if (status == ReadStatus.stop) {
140 | break;
141 | }
142 |
143 | if (status == ReadStatus.skip) {
144 | fc.position(fc.position() + partSize);
145 | continue;
146 | }
147 |
148 | if (status == ReadStatus.read) {
149 | ByteBuffer bb = ByteBuffer.allocate(partSize);
150 | int bytesRead = fc.read(bb);
151 | if (bytesRead == -1) {
152 | break;
153 | }
154 | byte[] bytes = bb.array();
155 | if (bytesRead != partSize) {// trim
156 | bytes = Arrays.copyOf(bytes, bytesRead);
157 | }
158 | String partName = createFileName(fileName, i);
159 | listener.onRead(partName);
160 | parts.put(new Part(partName, bytes));
161 | }
162 | }
163 | } finally {
164 | if (fis != null) {
165 | try {
166 | fis.close();
167 | } catch (Exception e) {
168 | }
169 | }
170 | parts.put(Part.NULL);// put end signal.
171 | }
172 |
173 | return "read";
174 | }
175 |
176 | /**
177 | * Create file name of part.
178 | * bigfile.avi = [bigfile.avi.0, bigfile.avi.1, bigfile.avi.2 ...]
179 | * @param fileName
180 | * @param i
181 | * @return
182 | */
183 | protected String createFileName(String fileName, int i) {
184 | return fileName + "." + i;// start by 0.
185 | // return fileName + (i == 0 ? "" : ("." + i));
186 | }
187 |
188 | private ReadStatus getReadStatus(int i, List indexes) {
189 |
190 | if (indexes == null || indexes.contains(i)) {
191 | return ReadStatus.read;
192 | }
193 |
194 | if (i > indexes.get(indexes.size() - 1)) {
195 | return ReadStatus.stop;
196 | }
197 |
198 | return ReadStatus.skip;
199 | }
200 | };
201 |
202 | private static enum ReadStatus {
203 | stop, skip, read
204 | }
205 |
206 | private class UploadTask implements Callable {
207 |
208 | private String name;
209 |
210 | public UploadTask(String name) {
211 | this.name = name;
212 | }
213 |
214 | @Override
215 | public String call() throws Exception {
216 |
217 | while (true) {
218 |
219 | Part part = parts.take();
220 | if (part == Part.NULL) {
221 | parts.add(Part.NULL);// notify others to stop.
222 | break;
223 | }
224 |
225 | String partName = part.getName();
226 | listener.onUpload(partName);
227 | uploader.upload(part);
228 | listener.onPartDone(partName);
229 | }
230 | return name;
231 | }
232 | }
233 |
234 | private Callable notifyTask = new Callable() {
235 | @Override
236 | public String call() throws Exception {
237 | uploader.done(file.getName(), getPartCount());
238 | return "notify";
239 | }
240 | };
241 | }
242 |
--------------------------------------------------------------------------------
/src/main/java/cn/clxy/upload/Uploader.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | public interface Uploader {
9 |
10 | /**
11 | * Upload a part.
12 | * @param part
13 | */
14 | void upload(Part part);
15 |
16 | /**
17 | * Notify server all uploading is done.
18 | * @param fileName
19 | * @param partCount
20 | */
21 | void done(String fileName, long partCount);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/bigFileUpload.properties:
--------------------------------------------------------------------------------
1 | url=http://192.168.1.99:8080/ssm/common/upload
2 |
3 | keyFile=file
4 | keyFileName=fileName
5 | keyPartCount=partCount
6 |
7 | maxUpload=5
8 | #unit:second
9 | timeOut=120
10 |
11 | #unit:k
12 | partSize=100
13 | maxRead=5
14 |
--------------------------------------------------------------------------------
/src/main/resources/commons-logging.properties:
--------------------------------------------------------------------------------
1 | .level=DEBUG
--------------------------------------------------------------------------------
/src/test/java/cn/clxy/upload/UploadFileServiceTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 CLXY Studio.
3 | * This content is released under the (Link Goes Here) MIT License.
4 | * http://en.wikipedia.org/wiki/MIT_License
5 | */
6 | package cn.clxy.upload;
7 |
8 | public class UploadFileServiceTest {
9 |
10 | public static void main(String[] args) {
11 |
12 | UploadFileService service = null;
13 | try {
14 |
15 | service = new UploadFileService("D:\\test.jpg");
16 | service.upload();
17 |
18 | service = new UploadFileService("D:\\test.jpg");
19 | service.retry(1, 2);
20 | } catch (Exception e) {
21 | e.printStackTrace();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------