28
28
29
29
import org .apache .commons .io .input .BoundedInputStream ;
30
30
import org .apache .hadoop .fs .FSInputStream ;
31
+ import org .apache .http .HttpStatus ;
31
32
32
33
import com .google .common .annotations .VisibleForTesting ;
33
34
import com .google .common .net .HttpHeaders ;
@@ -127,12 +128,7 @@ protected InputStream openInputStream() throws IOException {
127
128
fileLength = null ;
128
129
} else {
129
130
// for non-chunked transfer-encoding, get content-length
130
- final String cl = connection .getHeaderField (HttpHeaders .CONTENT_LENGTH );
131
- if (cl == null ) {
132
- throw new IOException (HttpHeaders .CONTENT_LENGTH + " is missing: "
133
- + headers );
134
- }
135
- final long streamlength = Long .parseLong (cl );
131
+ long streamlength = getStreamLength (connection , headers );
136
132
fileLength = startPos + streamlength ;
137
133
138
134
// Java has a bug with >2GB request streams. It won't bounds check
@@ -143,6 +139,36 @@ protected InputStream openInputStream() throws IOException {
143
139
return in ;
144
140
}
145
141
142
+ private static long getStreamLength (HttpURLConnection connection ,
143
+ Map <String , List <String >> headers ) throws IOException {
144
+ String cl = connection .getHeaderField (HttpHeaders .CONTENT_LENGTH );
145
+ if (cl == null ) {
146
+ // Try to get the content length by parsing the content range
147
+ // because HftpFileSystem does not return the content length
148
+ // if the content is partial.
149
+ if (connection .getResponseCode () == HttpStatus .SC_PARTIAL_CONTENT ) {
150
+ cl = connection .getHeaderField (HttpHeaders .CONTENT_RANGE );
151
+ return getLengthFromRange (cl );
152
+ } else {
153
+ throw new IOException (HttpHeaders .CONTENT_LENGTH + " is missing: "
154
+ + headers );
155
+ }
156
+ }
157
+ return Long .parseLong (cl );
158
+ }
159
+
160
+ private static long getLengthFromRange (String cl ) throws IOException {
161
+ try {
162
+
163
+ String [] str = cl .substring (6 ).split ("[-/]" );
164
+ return Long .parseLong (str [1 ]) - Long .parseLong (str [0 ]) + 1 ;
165
+ } catch (Exception e ) {
166
+ throw new IOException (
167
+ "failed to get content length by parsing the content range: " + cl
168
+ + " " + e .getMessage ());
169
+ }
170
+ }
171
+
146
172
private static boolean isChunkedTransferEncoding (
147
173
final Map <String , List <String >> headers ) {
148
174
return contains (headers , HttpHeaders .TRANSFER_ENCODING , "chunked" )
0 commit comments