Android webview - 如何从外部存储中获取文件

Posted

技术标签:

【中文标题】Android webview - 如何从外部存储中获取文件【英文标题】:Android webview - how to fetch a file from external storage 【发布时间】:2021-12-09 21:37:31 【问题描述】:

我有一个使用 webview 包裹网络应用的移动应用。

网络应用有一个按钮可以打开一个大的 .zip 文件(例如 100 MB)。 用户单击一个按钮,然后选择一个 .zip 文件。 这会触发一个带有 File (Blob) 类型变量的 onChange 函数,其中包括如下属性:

文件名 文件大小 文件类型(应用程序/zip)

javascript 代码然后解析 .zip 文件,提取其中的特定数据并在网络应用程序中使用它。

当通过 Chrome 浏览器调用应用程序时,这在网络应用程序中运行良好。 比如在安卓手机的chrome浏览器中操作,我可以拉取.zip文件并在web-app中打开。

我也想这样做但使用移动应用程序。 我可以使用文件选择器获取 .zip 文件,并将其传递给 Webview,但我无法从 Javascript 代码中获取文件。

作为参考,我可以通过使用 stringBuilder 创建 data_uri 并传递内容(作为 data:image/jpeg;base64)来传递图像。 但是 zip 文件要大得多。

从 Javascript 端调用 fetch(fileUri) 时出现错误。 我正在使用以下 uri /storage/emulated/0/android/data/com.example/files/Download/file2.zip 提取成功但返回一个大小为 165 的 blob(即不是文件的实际大小),其中包含错误消息:


      "error": "Not Found", 
      "message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."

程序流程是这样的:

我通过 FileChooser 选择了一个 .zip 文件。 在onActivityResult中,uri值为/document/msf:12858(通过uri = intent.getData();查看) uri需要映射成真实路径文件url,这样fileUrl才会传给webview。 Webview 然后将使用 fileUrl 获取文件。

我搜索了使用FileChooser选择文件时如何获取真实路径文件url,发现 this 和 this 链接。

我无法获得真正的文件路径,所以我决定读取文件并将其写入另一个位置,这样我就可以获得文件路径。 (这样做效率不高,只是为了检查功能)。

我使用以下代码创建新文件:

InputStream stream = context.getContentResolver().openInputStream(uri);
File file2 = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "file2.zip");
writeBytesToFile(stream, file2);

我在创建文件时没有看到任何错误,并且在创建文件时,读取和写入新文件的字节数符合预期。 对于 file2,我得到的值为:/storage/emulated/0/Android/data/com.example/files/Download/file2.zip

然后,在 Javascript 代码中,我获取此文件路径。 但我得到了一个带有上述“文件未找到”内容的 Blob。

所以:

如何验证文件确实已创建,并且可以从 webview 获取路径? 如何获取原选中文件的真实文件路径,从而不必为了获取文件路径而将原文件读写到新位置?

谢谢

【问题讨论】:

我让用户选择一个 zip 文件,在该文件上我在 onActivityResult 中获得一个内容方案 uri。我想将该 uri 传输到应该处理 zip 文件的 javascript 代码。但是 javascript 代码无法处理内容方案 uri,所以我尝试将 uri 转换为文件系统路径。这在现代 Android 设备上是不可能的。所以我决定从 uri 复制到文件系统并使用副本的路径。令我惊讶的是,Javascript 无法处理这条路径。 请告诉我上面的描述有什么问题。 对不起,我被上面的描述弄糊涂了。它总结了我的问题。所以,这是不可能的,我会问一个更基本的问题。如何将大型 .zip 文件的内容放入我的 Javascript 代码中? 我向您展示了您应该如何发布您的问题。你的结论是......不可能是错误的。制作副本并使用副本路径应该可以。 【参考方案1】:

通过执行以下步骤,我能够从外部存储中获取文件:

创建初始 uri (uri1) uri由以下人员创建: 通过在存储目录中创建一个临时文件 (file1) context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) 我不确定为什么需要创建临时文件,但如果我不创建文件,我将无法获取 uri。 创建文件3 通过以下方式获取 uri Uri uri1 = FileProvider.getUriForFile(context, "com.example.android.fileprovider", file1); 创建具有以下属性的意图: Intent.ACTION_OPEN_DOCUMENT category: Intent.CATEGORY_OPENABLE type: "application/zip" extra attribute: fileIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri1); 这将打开一个对话框,用于在Downloads 目录中选择可打开的 zip 文件, 选择文件后,会创建一个包含所选文件名称的新 uri (uri2)。 通过以下方式提取文件名 String fileName = getFileName(context, uri2); 通过附加文件名创建 dirPath dirPath = "/data/user/0/com.example/" + fileName; 如果dirPath 不存在(第一次),则将文件写入其dirPath 位置。 在连续的情况下 dirPath 存在,因此无需重新写入文件。 使用常规 Java 方法打开文件,例如通过 ZipFile zip = new ZipFile(dirPath);

【讨论】:

以上是关于Android webview - 如何从外部存储中获取文件的主要内容,如果未能解决你的问题,请参考以下文章

Android - 如何在 WebView 中访问本地存储值?

Android 下的 WebView 中数据如何保存

Android WebView是否需要打开外部URL的权限?

在webview中单击按钮后,如何在android应用程序中从webview打开外部应用程序?

将 HTML 文件中的外部 javascript 文件从 android assets 文件夹加载到 WebView

如何在WebView Android中过滤手机和其他Web链接