Skip to content

Commit

Permalink
fix: read local files on Android for 'file:///...' (#82)
Browse files Browse the repository at this point in the history
* fix: read local files on Android for 'file:///...'

* fix: alter read to prevent out of memory error
  • Loading branch information
davidgaag authored Sep 25, 2024
1 parent 15d77ec commit 478f124
Showing 1 changed file with 60 additions and 10 deletions.
70 changes: 60 additions & 10 deletions android/src/main/java/com/tflite/TfliteModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Objects;

import okhttp3.OkHttpClient;
import okhttp3.Request;
Expand Down Expand Up @@ -68,17 +72,41 @@ public static byte[] fetchByteDataFromUrl(String url) throws Exception {
}

if (uri != null) {
// It's a URL/http resource
Request request = new Request.Builder().url(uri.toString()).build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
return response.body().bytes();
} else {
throw new RuntimeException("Response was not successful!");
if (Objects.equals(uri.getScheme(), "file")) {
// It's a file URL
String path = Objects.requireNonNull(uri.getPath(), "File path cannot be null");
File file = new File(path);

// Check if file exists and is readable
if (!file.exists() || !file.canRead()) {
throw new IOException("File does not exist or is not readable: " + path);
}

// Check if the file has a .tflite extension
if (!file.getName().toLowerCase().endsWith(".tflite")) {
throw new SecurityException("Only .tflite files are allowed");
}

// Read the file
try (FileInputStream stream = new FileInputStream(file)) {
return getLocalFileBytes(stream, file);
} catch (IOException e) {
Log.e(NAME, "Error reading file: " + path, e);
throw new RuntimeException("Failed to read file: " + path, e);
}
} else {
// It's a network URL/http resource
Request request = new Request.Builder().url(uri.toString()).build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
return response.body().bytes();
} else {
throw new RuntimeException("Response was not successful!");
}
} catch (Exception ex) {
Log.e(NAME, "Failed to fetch URL " + url + "!", ex);
throw ex;
}
} catch (Exception ex) {
Log.e(NAME, "Failed to fetch URL " + url + "!", ex);
throw ex;
}
} else if (resourceId != null) {
// It's bundled into the Android resources/assets
Expand Down Expand Up @@ -127,4 +155,26 @@ public boolean install() {
}

private static native boolean nativeInstall(long jsiPtr, CallInvokerHolderImpl jsCallInvoker);

private static byte[] getLocalFileBytes(InputStream stream, File file) throws IOException {
long fileSize = file.length();

if (fileSize > Integer.MAX_VALUE) {
throw new IOException("File is too large to read into memory");
}

byte[] data = new byte[(int) fileSize];

int bytesRead = 0;
int chunk;
while (bytesRead < fileSize && (chunk = stream.read(data, bytesRead, (int)fileSize - bytesRead)) != -1) {
bytesRead += chunk;
}

if (bytesRead != fileSize) {
throw new IOException("Could not completely read file " + file.getName());
}

return data;
}
}

0 comments on commit 478f124

Please sign in to comment.