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



我有一个移动应用程序,围绕web应用程序,使用webview。

web应用程序有一个按钮打开一个大的。zip文件(例如100 MB)。
用户单击一个按钮,并选择一个.zip文件。
这会触发一个带有File (Blob)类型变量的onChange函数,该变量包含如下属性:文件名

  • 文件大小
  • 文件类型(application/zip)

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

这在web应用程序中工作得很好,当应用程序通过Chrome浏览器调用时。
例如,当在Android手机上的chrome浏览器中操作时,我可以拉出。zip文件并在web-app中打开它。

我想做同样的,但使用移动应用程序.
我能够使用文件选择器挑选。zip文件,并将其传递给Webview,但我有问题,从Javascript代码中获取文件。

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

从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获取文件。

我搜索如何获得真正的路径文件url时,选择FileChooser文件,并发现This, and This links.

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

我使用以下代码创建新文件:
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 "file-not-found">

:

  • 我如何验证文件确实被创建,路径可以从webview获取?
  • 我怎样才能得到原来所选文件的真实文件路径,这样我就不必为了得到文件路径而把原来的文件读写到新的位置了?

感谢

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

  • 创建一个初始uri (uri1)uri是由:
    • 通过在存储目录中创建临时文件(file1)context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
      我不知道为什么需要创建临时文件,但如果我不创建文件,我就无法获得uri。createFile3
    • 通过获取uriUri uri1 = FileProvider。getUriForFile(context, "com.example.android.fileprovider", file1);
    • 创建一个带有以下属性的intent:
      • 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);
  • 通过附加文件名创建dirPathdirPath = "/data/user/0/com.example/" + fileName;
  • 如果dirPath不存在(第一次),将文件写入dirPath位置。
  • 在连续的情况下,dirPath存在,所以不需要重写文件。
  • 使用常规的Java方法打开文件,例如viaZipFile zip = new ZipFile(dirPath);