2828
2929import org .apache .commons .io .input .BoundedInputStream ;
3030import org .apache .hadoop .fs .FSInputStream ;
31+ import org .apache .http .HttpStatus ;
3132
3233import com .google .common .annotations .VisibleForTesting ;
3334import com .google .common .net .HttpHeaders ;
@@ -127,12 +128,7 @@ protected InputStream openInputStream() throws IOException {
127128 fileLength = null ;
128129 } else {
129130 // 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 );
136132 fileLength = startPos + streamlength ;
137133
138134 // Java has a bug with >2GB request streams. It won't bounds check
@@ -143,6 +139,36 @@ protected InputStream openInputStream() throws IOException {
143139 return in ;
144140 }
145141
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+
146172 private static boolean isChunkedTransferEncoding (
147173 final Map <String , List <String >> headers ) {
148174 return contains (headers , HttpHeaders .TRANSFER_ENCODING , "chunked" )
0 commit comments