mirror of
https://github.com/apache/cordova-android.git
synced 2025-01-19 15:12:51 +08:00
Code clean-up of FileTransfer
- Fix warnings about toLowerCase() - Don't assume connections are HTTP (fails for file://) - Use StringBuilder - Remove no-ops of disconnect() & keep-alive
This commit is contained in:
parent
db099e7722
commit
8ab7278db2
@ -20,7 +20,6 @@ package org.apache.cordova;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -33,6 +32,7 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
@ -200,7 +200,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
|
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean useHttps = url.getProtocol().toLowerCase().equals("https");
|
final boolean useHttps = url.getProtocol().equals("https");
|
||||||
|
|
||||||
final RequestContext context = new RequestContext(source, target, callbackContext);
|
final RequestContext context = new RequestContext(source, target, callbackContext);
|
||||||
synchronized (activeRequests) {
|
synchronized (activeRequests) {
|
||||||
@ -258,7 +258,6 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
|
|
||||||
// Use a post method.
|
// Use a post method.
|
||||||
conn.setRequestMethod("POST");
|
conn.setRequestMethod("POST");
|
||||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
|
||||||
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
|
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
|
||||||
|
|
||||||
// Set the cookies on the response
|
// Set the cookies on the response
|
||||||
@ -291,37 +290,35 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
* Store the non-file portions of the multipart data as a string, so that we can add it
|
* Store the non-file portions of the multipart data as a string, so that we can add it
|
||||||
* to the contentSize, since it is part of the body of the HTTP request.
|
* to the contentSize, since it is part of the body of the HTTP request.
|
||||||
*/
|
*/
|
||||||
String extraParams = "";
|
StringBuilder beforeData = new StringBuilder();
|
||||||
try {
|
try {
|
||||||
for (Iterator<?> iter = params.keys(); iter.hasNext();) {
|
for (Iterator<?> iter = params.keys(); iter.hasNext();) {
|
||||||
Object key = iter.next();
|
Object key = iter.next();
|
||||||
if(!String.valueOf(key).equals("headers"))
|
if(!String.valueOf(key).equals("headers"))
|
||||||
{
|
{
|
||||||
extraParams += LINE_START + BOUNDARY + LINE_END;
|
beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
|
||||||
extraParams += "Content-Disposition: form-data; name=\"" + key.toString() + "\";";
|
beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append('"');
|
||||||
extraParams += LINE_END + LINE_END;
|
beforeData.append(LINE_END).append(LINE_END);
|
||||||
extraParams += params.getString(key.toString());
|
beforeData.append(params.getString(key.toString()));
|
||||||
extraParams += LINE_END;
|
beforeData.append(LINE_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(LOG_TAG, e.getMessage(), e);
|
Log.e(LOG_TAG, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
extraParams += LINE_START + BOUNDARY + LINE_END;
|
beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
|
||||||
extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
|
beforeData.append("Content-Disposition: form-data; name=\"").append(fileKey).append("\";");
|
||||||
byte[] extraBytes = extraParams.getBytes("UTF-8");
|
beforeData.append(" filename=\"").append(fileName).append('"').append(LINE_END);
|
||||||
|
beforeData.append("Content-Type: ").append(mimeType).append(LINE_END).append(LINE_END);
|
||||||
String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
|
byte[] beforeDataBytes = beforeData.toString().getBytes("UTF-8");
|
||||||
String tailParams = LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END;
|
byte[] tailParamsBytes = (LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END).getBytes("UTF-8");
|
||||||
byte[] fileNameBytes = fileName.getBytes("UTF-8");
|
|
||||||
|
|
||||||
|
|
||||||
// Get a input stream of the file on the phone
|
// Get a input stream of the file on the phone
|
||||||
InputStream sourceInputStream = getPathFromUri(source);
|
InputStream sourceInputStream = getPathFromUri(source);
|
||||||
|
|
||||||
int stringLength = extraBytes.length + midParams.length() + tailParams.length() + fileNameBytes.length;
|
int stringLength = beforeDataBytes.length + tailParamsBytes.length;
|
||||||
Log.d(LOG_TAG, "String Length: " + stringLength);
|
|
||||||
if (sourceInputStream instanceof FileInputStream) {
|
if (sourceInputStream instanceof FileInputStream) {
|
||||||
fixedLength = (int) ((FileInputStream)sourceInputStream).getChannel().size() + stringLength;
|
fixedLength = (int) ((FileInputStream)sourceInputStream).getChannel().size() + stringLength;
|
||||||
progress.setLengthComputable(true);
|
progress.setLengthComputable(true);
|
||||||
@ -333,7 +330,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
// It also causes OOM if HTTPS is used, even on newer devices.
|
// It also causes OOM if HTTPS is used, even on newer devices.
|
||||||
boolean useChunkedMode = chunkedMode && (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO || useHttps);
|
boolean useChunkedMode = chunkedMode && (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO || useHttps);
|
||||||
useChunkedMode = useChunkedMode || (fixedLength == -1);
|
useChunkedMode = useChunkedMode || (fixedLength == -1);
|
||||||
|
|
||||||
if (useChunkedMode) {
|
if (useChunkedMode) {
|
||||||
conn.setChunkedStreamingMode(MAX_BUFFER_SIZE);
|
conn.setChunkedStreamingMode(MAX_BUFFER_SIZE);
|
||||||
// Although setChunkedStreamingMode sets this header, setting it explicitly here works
|
// Although setChunkedStreamingMode sets this header, setting it explicitly here works
|
||||||
@ -343,19 +340,20 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
conn.setFixedLengthStreamingMode(fixedLength);
|
conn.setFixedLengthStreamingMode(fixedLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataOutputStream dos = null;
|
conn.connect();
|
||||||
|
|
||||||
|
OutputStream sendStream = null;
|
||||||
try {
|
try {
|
||||||
dos = new DataOutputStream( conn.getOutputStream() );
|
sendStream = conn.getOutputStream();
|
||||||
synchronized (context) {
|
synchronized (context) {
|
||||||
if (context.aborted) {
|
if (context.aborted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.currentOutputStream = dos;
|
context.currentOutputStream = sendStream;
|
||||||
}
|
}
|
||||||
//We don't want to change encoding, we just want this to write for all Unicode.
|
//We don't want to change encoding, we just want this to write for all Unicode.
|
||||||
dos.write(extraBytes);
|
sendStream.write(beforeDataBytes);
|
||||||
dos.write(fileNameBytes);
|
totalBytes += beforeDataBytes.length;
|
||||||
dos.writeBytes(midParams);
|
|
||||||
|
|
||||||
// create a buffer of maximum size
|
// create a buffer of maximum size
|
||||||
int bytesAvailable = sourceInputStream.available();
|
int bytesAvailable = sourceInputStream.available();
|
||||||
@ -367,9 +365,9 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
|
|
||||||
long prevBytesRead = 0;
|
long prevBytesRead = 0;
|
||||||
while (bytesRead > 0) {
|
while (bytesRead > 0) {
|
||||||
totalBytes += bytesRead;
|
|
||||||
result.setBytesSent(totalBytes);
|
result.setBytesSent(totalBytes);
|
||||||
dos.write(buffer, 0, bytesRead);
|
sendStream.write(buffer, 0, bytesRead);
|
||||||
|
totalBytes += bytesRead;
|
||||||
if (totalBytes > prevBytesRead + 102400) {
|
if (totalBytes > prevBytesRead + 102400) {
|
||||||
prevBytesRead = totalBytes;
|
prevBytesRead = totalBytes;
|
||||||
Log.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
|
Log.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
|
||||||
@ -386,17 +384,21 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send multipart form data necessary after file data...
|
// send multipart form data necessary after file data...
|
||||||
dos.writeBytes(tailParams);
|
sendStream.write(tailParamsBytes);
|
||||||
dos.flush();
|
totalBytes += tailParamsBytes.length;
|
||||||
|
sendStream.flush();
|
||||||
} finally {
|
} finally {
|
||||||
safeClose(sourceInputStream);
|
safeClose(sourceInputStream);
|
||||||
safeClose(dos);
|
safeClose(sendStream);
|
||||||
}
|
}
|
||||||
context.currentOutputStream = null;
|
context.currentOutputStream = null;
|
||||||
|
Log.d(LOG_TAG, "Sent " + totalBytes + " of " + fixedLength);
|
||||||
|
|
||||||
//------------------ read the SERVER RESPONSE
|
//------------------ read the SERVER RESPONSE
|
||||||
String responseString;
|
String responseString;
|
||||||
int responseCode = conn.getResponseCode();
|
int responseCode = conn.getResponseCode();
|
||||||
|
Log.d(LOG_TAG, "response code: " + responseCode);
|
||||||
|
Log.d(LOG_TAG, "response headers: " + conn.getHeaderFields());
|
||||||
InputStream inStream = null;
|
InputStream inStream = null;
|
||||||
try {
|
try {
|
||||||
inStream = getInputStream(conn);
|
inStream = getInputStream(conn);
|
||||||
@ -407,8 +409,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
context.currentInputStream = inStream;
|
context.currentInputStream = inStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(1024, conn.getContentLength()));
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
// write bytes to file
|
// write bytes to file
|
||||||
@ -459,8 +460,6 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
https.setHostnameVerifier(oldHostnameVerifier);
|
https.setHostnameVerifier(oldHostnameVerifier);
|
||||||
https.setSSLSocketFactory(oldSocketFactory);
|
https.setSSLSocketFactory(oldSocketFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.disconnect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,7 +475,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InputStream getInputStream(HttpURLConnection conn) throws IOException {
|
private static InputStream getInputStream(URLConnection conn) throws IOException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||||
return new DoneHandlerInputStream(conn.getInputStream());
|
return new DoneHandlerInputStream(conn.getInputStream());
|
||||||
}
|
}
|
||||||
@ -527,13 +526,15 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
return oldFactory;
|
return oldFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JSONObject createFileTransferError(int errorCode, String source, String target, HttpURLConnection connection) {
|
private static JSONObject createFileTransferError(int errorCode, String source, String target, URLConnection connection) {
|
||||||
|
|
||||||
Integer httpStatus = null;
|
int httpStatus = 0;
|
||||||
|
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
try {
|
try {
|
||||||
httpStatus = connection.getResponseCode();
|
if (connection instanceof HttpURLConnection) {
|
||||||
|
httpStatus = ((HttpURLConnection)connection).getResponseCode();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
|
Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
|
||||||
}
|
}
|
||||||
@ -602,7 +603,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
|
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean useHttps = url.getProtocol().toLowerCase().equals("https");
|
final boolean useHttps = url.getProtocol().equals("https");
|
||||||
|
|
||||||
if (!Config.isUrlWhiteListed(source)) {
|
if (!Config.isUrlWhiteListed(source)) {
|
||||||
Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
|
Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
|
||||||
@ -622,7 +623,7 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
if (context.aborted) {
|
if (context.aborted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HttpURLConnection connection = null;
|
URLConnection connection = null;
|
||||||
HostnameVerifier oldHostnameVerifier = null;
|
HostnameVerifier oldHostnameVerifier = null;
|
||||||
SSLSocketFactory oldSocketFactory = null;
|
SSLSocketFactory oldSocketFactory = null;
|
||||||
|
|
||||||
@ -654,10 +655,12 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
}
|
}
|
||||||
// Return a standard HTTP connection
|
// Return a standard HTTP connection
|
||||||
else {
|
else {
|
||||||
connection = (HttpURLConnection) url.openConnection();
|
connection = url.openConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.setRequestMethod("GET");
|
if (connection instanceof HttpURLConnection) {
|
||||||
|
((HttpURLConnection)connection).setRequestMethod("GET");
|
||||||
|
}
|
||||||
|
|
||||||
//Add cookie support
|
//Add cookie support
|
||||||
String cookie = CookieManager.getInstance().getCookie(source);
|
String cookie = CookieManager.getInstance().getCookie(source);
|
||||||
@ -743,8 +746,6 @@ public class FileTransfer extends CordovaPlugin {
|
|||||||
https.setHostnameVerifier(oldHostnameVerifier);
|
https.setHostnameVerifier(oldHostnameVerifier);
|
||||||
https.setSSLSocketFactory(oldSocketFactory);
|
https.setSSLSocketFactory(oldSocketFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.disconnect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user