diff --git a/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java b/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java index bee7ccd269d..65634d2f950 100644 --- a/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java +++ b/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java @@ -10,6 +10,7 @@ import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilterOutputStream; @@ -32,7 +33,6 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -221,6 +221,7 @@ private void handleResponse(HttpURLConnection connection) throws IOException charset = "UTF-8"; } responseData = null; + responseText = null; int status = connection.getResponseCode(); InputStream in; @@ -241,7 +242,7 @@ private void handleResponse(HttpURLConnection connection) throws IOException Log.d(TAG, "Content length: " + contentLength, Log.DEBUG_MODE); int count = 0; long totalSize = 0; - byte[] buf = new byte[4096]; + byte[] buf = new byte[8192]; Log.d(TAG, "Available: " + is.available(), Log.DEBUG_MODE); while ((count = is.read(buf)) != -1) { @@ -250,7 +251,6 @@ private void handleResponse(HttpURLConnection connection) throws IOException } totalSize += count; try { - responseText = new String(Arrays.copyOfRange(buf, 0, count)); handleEntityData(buf, count, totalSize, contentLength); } catch (IOException e) { Log.e(TAG, "Error handling entity data", e); @@ -346,15 +346,10 @@ private void handleEntityData(byte[] data, int size, long totalSize, long conten KrollDict callbackData = new KrollDict(); callbackData.put("totalCount", contentLength); callbackData.put("totalSize", totalSize); - callbackData.put("size", size); + callbackData.put(TiC.PROPERTY_SIZE, size); - byte[] blobData = new byte[size]; - System.arraycopy(data, 0, blobData, 0, size); - - TiBlob blob = TiBlob.blobFromData(blobData, contentType); - callbackData.put("blob", blob); - double progress = ((double) totalSize) / ((double) contentLength); // return progress as -1 if it is outside the valid range + double progress = ((double) totalSize) / ((double) contentLength); if (progress > 1 || progress < 0) { progress = NetworkModule.PROGRESS_UNKNOWN; } @@ -365,9 +360,19 @@ private void handleEntityData(byte[] data, int size, long totalSize, long conten private void finishedReceivingEntityData(long contentLength) throws IOException { + if (responseOut == null) { + return; + } + + responseOut.flush(); if (responseOut instanceof ByteArrayOutputStream) { ByteArrayOutputStream byteStream = (ByteArrayOutputStream) responseOut; responseData = TiBlob.blobFromData(byteStream.toByteArray(), contentType); + } else if (responseOut instanceof FileOutputStream) { + FileDescriptor fileDescriptor = ((FileOutputStream) responseOut).getFD(); + if (fileDescriptor != null) { + fileDescriptor.sync(); + } } responseOut.close(); responseOut = null; @@ -416,7 +421,6 @@ public TiHTTPClient(HTTPClientProxy proxy) httpClientThreadCounter = new AtomicInteger(); } readyState = 0; - responseText = ""; connected = false; this.nvPairs = new ArrayList(); this.parts = new HashMap(); @@ -484,8 +488,18 @@ private String decodeResponseData(String charsetName) return null; } + byte[] byteBuffer = null; + if (responseData != null) { + byteBuffer = responseData.getBytes(); + } else if (responseOut instanceof ByteArrayOutputStream) { + byteBuffer = ((ByteArrayOutputStream) responseOut).toByteArray(); + } + if (byteBuffer == null) { + return null; + } + CharsetDecoder decoder = charset.newDecoder(); - ByteBuffer in = ByteBuffer.wrap(responseData.getBytes()); + ByteBuffer in = ByteBuffer.wrap(byteBuffer); try { CharBuffer decodedText = decoder.decode(in); @@ -524,58 +538,86 @@ private String detectResponseDataEncoding() return null; } - CharSequence responseSequence = responseData.toString(); - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(responseSequence); - if (matcher.find()) { - return matcher.group(1); + CharSequence responseSequence = null; + if (responseData != null) { + responseSequence = responseData.toString(); + } else if (responseOut instanceof ByteArrayOutputStream) { + responseSequence = responseOut.toString(); + } + if (responseSequence != null) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(responseSequence); + if (matcher.find()) { + return matcher.group(1); + } } - return null; } public String getResponseText() { - if (responseText != null || responseData == null) { - return responseText; + // If we've already transcoded the response text below, then return it now. + if (this.responseText != null) { + return this.responseText; } // First try decoding the response data using the charset // specified in the response content-type header. - if (charset != null) { - responseText = decodeResponseData(charset); - if (responseText != null) { - return responseText; - } + String text = null; + if (this.charset != null) { + text = decodeResponseData(this.charset); } // If the first attempt to decode fails try detecting the correct // charset by scanning the response data. - String detectedCharset = detectResponseDataEncoding(); - if (detectedCharset != null) { - Log.d(TAG, "detected charset: " + detectedCharset, Log.DEBUG_MODE); - responseText = decodeResponseData(detectedCharset); - if (responseText != null) { - charset = detectedCharset; - return responseText; + if (text == null) { + String detectedCharset = detectResponseDataEncoding(); + if (detectedCharset != null) { + Log.d(TAG, "detected charset: " + detectedCharset, Log.DEBUG_MODE); + text = decodeResponseData(detectedCharset); + if (text != null) { + this.charset = detectedCharset; + } } } // As a last resort try our fallback charsets to decode the data. - for (String charset : FALLBACK_CHARSETS) { - responseText = decodeResponseData(charset); - if (responseText != null) { - return responseText; + if (text == null) { + for (String charset : FALLBACK_CHARSETS) { + text = decodeResponseData(charset); + if (text != null) { + this.charset = charset; + break; + } } } - Log.e(TAG, "Could not decode response text."); - return responseText; + // Log an error if we've failed to transcode the response above. + if (text == null) { + Log.e(TAG, "Could not decode response text."); + text = ""; + } + + // Store the response text for quick access later, but only if we've finished receiving the response. + if (this.responseOut == null) { + this.responseText = text; + } + + // Return the transcoded response text. + return text; } public TiBlob getResponseData() { - return responseData; + TiBlob blob = this.responseData; + if (blob == null) { + if (this.responseOut instanceof ByteArrayOutputStream) { + blob = TiBlob.blobFromData(((ByteArrayOutputStream) this.responseOut).toByteArray()); + } else if (this.responseText != null) { + blob = TiBlob.blobFromString(this.responseText); + } + } + return blob; } public DocumentProxy getResponseXML()