diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java index 551382ca6..121d1971b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java @@ -9,20 +9,22 @@ package com.facebook.react.modules.network; -import javax.annotation.Nullable; - +import android.content.Context; +import android.net.Uri; +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; import java.util.zip.GZIPOutputStream; - -import android.content.Context; -import android.net.Uri; - -import com.facebook.common.logging.FLog; -import com.facebook.react.common.ReactConstants; - +import javax.annotation.Nullable; import okhttp3.MediaType; import okhttp3.RequestBody; import okhttp3.internal.Util; @@ -38,6 +40,8 @@ import okio.Source; /*package*/ class RequestBodyUtil { private static final String CONTENT_ENCODING_GZIP = "gzip"; + private static final String NAME = "RequestBodyUtil"; + private static final String TEMP_FILE_SUFFIX = "temp"; /** * Returns whether encode type indicates the body needs to be gzip-ed. @@ -55,6 +59,10 @@ import okio.Source; String fileContentUriStr) { try { Uri fileContentUri = Uri.parse(fileContentUriStr); + + if (fileContentUri.getScheme().startsWith("http")) { + return getDownloadFileInputStream(context, fileContentUri); + } return context.getContentResolver().openInputStream(fileContentUri); } catch (Exception e) { FLog.e( @@ -66,11 +74,37 @@ import okio.Source; } /** - * Creates a RequestBody from a mediaType and gzip-ed body string + * Download and cache a file locally. This should be used when document picker returns a URI that + * points to a file on the network. Returns input stream for the downloaded file. */ - public static @Nullable RequestBody createGzip( - final MediaType mediaType, - final String body) { + private static InputStream getDownloadFileInputStream(Context context, Uri uri) + throws IOException { + final File outputDir = context.getApplicationContext().getCacheDir(); + final File file = File.createTempFile(NAME, TEMP_FILE_SUFFIX, outputDir); + file.deleteOnExit(); + + final URL url = new URL(uri.toString()); + final InputStream is = url.openStream(); + try { + final ReadableByteChannel channel = Channels.newChannel(is); + try { + final FileOutputStream stream = new FileOutputStream(file); + try { + stream.getChannel().transferFrom(channel, 0, Long.MAX_VALUE); + return new FileInputStream(file); + } finally { + stream.close(); + } + } finally { + channel.close(); + } + } finally { + is.close(); + } + } + + /** Creates a RequestBody from a mediaType and gzip-ed body string */ + public static @Nullable RequestBody createGzip(final MediaType mediaType, final String body) { ByteArrayOutputStream gzipByteArrayOutputStream = new ByteArrayOutputStream(); try { OutputStream gzipOutputStream = new GZIPOutputStream(gzipByteArrayOutputStream);