无法获取Blob形式接收的图片,仅能读取PDF问题求助
解决Android WebView中Blob图片转存失败的问题
看起来你的代码在处理PDF Blob时能正常工作,但图片转存失败,核心问题出在Base64字符串的前缀处理和可能的解码参数上,我来一步步帮你解决:
核心问题分析
FileReader.readAsDataURL()返回的base64字符串是包含MIME类型前缀的,比如图片会是 data:image/png;base64,/9j/4AAQSkZJRgABAQEAAAAAAAD/...,PDF则是data:application/pdf;base64,JVBERi0xLjMKJcfsj6IKNSAwIG9iago8PC9M...。而你当前直接用Base64.decode()解码带前缀的字符串,这会导致图片解码失败(PDF可能因为某些偶然情况能勉强解析,但其实也是不符合规范的)。
解决方案步骤
1. 移除Base64字符串的MIME前缀
在writeToSDFile方法中,先剥离掉前缀部分,只保留纯Base64内容:
private void writeToSDFile(String string, String fileName) { // 剥离base64前缀(data:xxx;base64,) String base64Content = string; if (string.contains("base64,")) { base64Content = string.split("base64,")[1]; } File root = android.os.Environment.getExternalStorageDirectory(); File dir = new File(root.getAbsolutePath() + "/" + Environment.DIRECTORY_DOWNLOADS); dir.mkdirs(); File file = new File(dir, fileName); try { // 使用NO_WRAP避免换行符导致的解码问题 byte[] data = android.util.Base64.decode(base64Content, Base64.NO_WRAP); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bos.write(data); bos.flush(); bos.close(); CommonUtilities._Log(TAG, "File Path " + file.getCanonicalPath()); CommonUtilities.showFolderIntent(this, dir); } catch (Exception e) { CommonUtilities._Log(TAG, Log.getStackTraceString(e)); } }
2. 确保文件名包含正确的图片后缀
从onDownloadStart的contentDisposition参数中解析出正确的文件名(包含后缀),避免保存的图片文件没有后缀导致系统无法识别:
web.setDownloadListener(new DownloadListener() { public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { CommonUtilities._Log(TAG, "url = " + url + " ,, userAgent = " + userAgent + " ,,contentDisposition " + contentDisposition + " ,, mimetype = " + mimetype + " ,, length= " + contentLength); // 解析contentDisposition获取带后缀的文件名 String fileName = "unknown_file"; if (contentDisposition != null) { String[] parts = contentDisposition.split("filename="); if (parts.length > 1) { fileName = parts[1].replace("\"", "").trim(); } } String s = "var request = new XMLHttpRequest();\n" + "request.open('GET', \"" + url + "\", true);\n" + "request.responseType = 'blob';\n" + "request.timeout = 30000;" + "request.onload = function() {\n" + " var reader = new FileReader();\n" + " reader.readAsDataURL(request.response); \n" + " reader.onloadend = function() {\n" + " base64data = reader.result; \n" + " Android.androidPay(base64data, \"" + fileName + "\")" + // 传递文件名 " }\n" + "}\n" + "request.send();"; WebLink.this.web.evaluateJavascript(s, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { CommonUtilities._Log(TAG, "value " + value); } }); } });
3. 更新Javascript接口方法
修改你的androidPay方法,接收base64数据和文件名两个参数:
@JavascriptInterface public void androidPay(String base64Data, String fileName) { writeToSDFile(base64Data, fileName); }
额外检查点
- 权限:确保你的App在Android 10及以上版本中,对Downloads目录的写入权限是正常的(公共Downloads目录不需要额外的WRITE_EXTERNAL_STORAGE权限,但如果是自定义目录则需要)。
- 超时设置:如果是大尺寸图片,可以适当调整XMLHttpRequest的超时时间(比如改为60000毫秒)。
- 调试:在Javascript中打开
console.log(base64data),检查图片的base64字符串是否完整,有没有截断情况。
按照这些步骤修改后,应该就能正常转存图片Blob了。
内容的提问来源于stack exchange,提问作者Rahul Khurana




