From 5fa7295dc5baa542a621c2639972f0088a9c113e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Marcin=C4=8Do?= Date: Fri, 12 Jul 2024 14:32:34 +0200 Subject: [PATCH 1/2] fix(@capacitor/filesystem) Allow Filesystem.copy to copy content:// URIs on Android --- .../plugins/filesystem/Filesystem.java | 80 ++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java b/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java index 528e23d2a..b3d243f96 100644 --- a/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java +++ b/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java @@ -1,5 +1,7 @@ package com.capacitorjs.plugins.filesystem; +import static java.nio.channels.Channels.newChannel; + import android.content.Context; import android.net.Uri; import android.os.Environment; @@ -21,9 +23,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; +import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.FileChannel; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Locale; @@ -106,24 +112,13 @@ public File copy(String from, String directory, String to, String toDirectory, b toDirectory = directory; } - File fromObject = getFileObject(from, directory); + boolean isContentUri = Uri.parse(from).getScheme().equals("content"); File toObject = getFileObject(to, toDirectory); - if (fromObject == null) { - throw new CopyFailedException("from file is null"); - } if (toObject == null) { throw new CopyFailedException("to file is null"); } - if (toObject.equals(fromObject)) { - return toObject; - } - - if (!fromObject.exists()) { - throw new CopyFailedException("The source object does not exist"); - } - if (toObject.getParentFile().isFile()) { throw new CopyFailedException("The parent object of the destination is a file"); } @@ -136,16 +131,40 @@ public File copy(String from, String directory, String to, String toDirectory, b throw new CopyFailedException("Cannot overwrite a directory"); } - toObject.delete(); + if (isContentUri) { + InputStream fromObject = getInputStream(from, directory); - if (doRename) { - boolean modified = fromObject.renameTo(toObject); - if (!modified) { - throw new CopyFailedException("Unable to rename, unknown reason"); - } + toObject.delete(); + + copyContent(fromObject, toObject); + + return toObject; } else { - copyRecursively(fromObject, toObject); - } + File fromObject = getFileObject(from, directory); + + if (fromObject == null) { + throw new CopyFailedException("from file is null"); + } + + if (toObject.equals(fromObject)) { + return toObject; + } + + if (!fromObject.exists()) { + throw new CopyFailedException("The source object does not exist"); + } + + toObject.delete(); + + if (doRename) { + boolean modified = fromObject.renameTo(toObject); + if (!modified) { + throw new CopyFailedException("Unable to rename, unknown reason"); + } + } else { + copyRecursively(fromObject, toObject); + } + } return toObject; } @@ -303,6 +322,27 @@ public void copyRecursively(File src, File dst) throws IOException { } } + /** + * Helper function to copy content files + * + * @param srcStream The source location stream + * @param dstFile The destination location + * @throws IOException + */ + public void copyContent(InputStream srcStream, File dstFile) throws IOException { + if (!dstFile.getParentFile().exists()) { + dstFile.getParentFile().mkdirs(); + } + + if (!dstFile.exists()) { + dstFile.createNewFile(); + } + + try (ReadableByteChannel source = newChannel(srcStream); FileChannel destination = new FileOutputStream(dstFile).getChannel()) { + destination.transferFrom(source, 0, Long.MAX_VALUE); + } + } + public JSObject downloadFile(PluginCall call, Bridge bridge, HttpRequestHandler.ProgressEmitter emitter) throws IOException, URISyntaxException, JSONException { String urlString = call.getString("url", ""); From b5ad1fda1d6e3d70d4950a6a1eb9e46f65211d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Marcin=C4=8Do?= Date: Mon, 15 Jul 2024 14:57:57 +0200 Subject: [PATCH 2/2] fix(@capacitor/filesystem) Fix Filesystem.copy crashing on scheme-less paths --- .../java/com/capacitorjs/plugins/filesystem/Filesystem.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java b/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java index b3d243f96..a5c456cb0 100644 --- a/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java +++ b/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java @@ -112,7 +112,9 @@ public File copy(String from, String directory, String to, String toDirectory, b toDirectory = directory; } - boolean isContentUri = Uri.parse(from).getScheme().equals("content"); + String scheme = Uri.parse(from).getScheme(); + boolean isContentUri = scheme != null && scheme.equals("content"); + File toObject = getFileObject(to, toDirectory); if (toObject == null) {