debug(file): 添加文件下载功能的调试日志
- 在 FileSDK 的 saveBlobDownload 方法中添加解码、目录创建和文件写入的日志记录 - 在 XWebViewView 的 readBlobAndPost 函数中添加 JavaScript 端的数据读取和错误处理日志 - 添加锚点拦截和消息传递过程中的日志记录 - 在 blobdownload 处理流程中添加成功和失败的状态日志 - 增加文件保存到相册操作的结果日志记录
这个提交包含在:
父节点
d8c0abe510
当前提交
2bd497ead4
@ -251,7 +251,9 @@ object FileSDK {
|
||||
fileName: String,
|
||||
destination: FileDownloadDestination = FileDownloadDestination.Sandbox,
|
||||
): File {
|
||||
android.util.Log.d("XWV", "saveBlobDownload: fileName=$fileName, dest=$destination, b64Len=${base64Data.length}")
|
||||
val bytes = android.util.Base64.decode(base64Data, android.util.Base64.DEFAULT)
|
||||
android.util.Log.d("XWV", "saveBlobDownload: decoded ${bytes.size} bytes")
|
||||
val baseDir = when (destination) {
|
||||
FileDownloadDestination.PublicDownloads -> {
|
||||
val appName = context.applicationInfo.loadLabel(context.packageManager).toString()
|
||||
@ -260,14 +262,21 @@ object FileSDK {
|
||||
android.os.Environment.DIRECTORY_DOWNLOADS
|
||||
),
|
||||
appName,
|
||||
).apply { mkdirs() }
|
||||
).apply {
|
||||
val created = mkdirs()
|
||||
android.util.Log.d("XWV", "saveBlobDownload: PublicDownloads dir=$absolutePath, created=$created, exists=${exists()}")
|
||||
}
|
||||
}
|
||||
FileDownloadDestination.Sandbox -> {
|
||||
context.getExternalFilesDir(null) ?: context.filesDir
|
||||
(context.getExternalFilesDir(null) ?: context.filesDir).also {
|
||||
android.util.Log.d("XWV", "saveBlobDownload: Sandbox dir=${it.absolutePath}")
|
||||
}
|
||||
}
|
||||
}
|
||||
val target = uniqueFile(baseDir, fileName.takeIf { it.isNotBlank() } ?: "download.bin")
|
||||
android.util.Log.d("XWV", "saveBlobDownload: writing to ${target.absolutePath}")
|
||||
target.writeBytes(bytes)
|
||||
android.util.Log.d("XWV", "saveBlobDownload: done, size=${target.length()}")
|
||||
return target
|
||||
}
|
||||
|
||||
|
||||
@ -100,17 +100,29 @@ internal fun buildDialogOverrideJs(bridgeName: String) = """
|
||||
URL.revokeObjectURL = function() {};
|
||||
|
||||
function readBlobAndPost(blobUrl, filename) {
|
||||
console.log('[XWV] readBlobAndPost start, url=' + blobUrl + ', filename=' + filename);
|
||||
fetch(blobUrl)
|
||||
.then(function(r) { return r.blob(); })
|
||||
.then(function(r) {
|
||||
console.log('[XWV] fetch ok, size=' + r.size);
|
||||
return r.blob();
|
||||
})
|
||||
.then(function(blob) {
|
||||
console.log('[XWV] blob ok, size=' + blob.size + ', type=' + blob.type);
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
var b64 = reader.result.split(',')[1];
|
||||
console.log('[XWV] base64 ready, len=' + (b64 ? b64.length : 0));
|
||||
post({ __xwv: 'blobdownload', url: blobUrl, filename: filename, data: b64 });
|
||||
console.log('[XWV] blobdownload posted');
|
||||
};
|
||||
reader.onerror = function(e) {
|
||||
console.log('[XWV] FileReader error: ' + String(e));
|
||||
post({ __xwv: 'bloberror', msg: 'FileReader error: ' + String(e) });
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('[XWV] readBlobAndPost ERROR: ' + String(err));
|
||||
post({ __xwv: 'bloberror', msg: String(err) });
|
||||
});
|
||||
}
|
||||
@ -125,6 +137,7 @@ internal fun buildDialogOverrideJs(bridgeName: String) = """
|
||||
var hasDownloadAttr = el.hasAttribute('download');
|
||||
var dlName = el.getAttribute('download') || '';
|
||||
var isDL = hasDownloadAttr || dlRe.test(href);
|
||||
console.log('[XWV] tryInterceptAnchor href=' + href + ', hasDownload=' + hasDownloadAttr + ', isDL=' + isDL);
|
||||
if (isDL) {
|
||||
if (e) { e.preventDefault(); e.stopPropagation(); }
|
||||
if (href.startsWith('blob:')) {
|
||||
@ -180,9 +193,11 @@ internal class XWebViewJsBridge(
|
||||
) {
|
||||
@JavascriptInterface
|
||||
fun postMessage(data: String) {
|
||||
android.util.Log.d("XWV", "postMessage: ${data.take(200)}")
|
||||
mainHandler.post {
|
||||
val json = runCatching { JSONObject(data) }.getOrNull()
|
||||
val xwv = json?.optString("__xwv")?.takeIf { it.isNotEmpty() }
|
||||
android.util.Log.d("XWV", "postMessage parsed: xwv=$xwv")
|
||||
if (xwv != null && json != null) {
|
||||
onXwvMessage()?.invoke(xwv, json)
|
||||
} else {
|
||||
@ -229,6 +244,7 @@ fun XWebViewView(
|
||||
|
||||
// Handles __xwv: 'download' / 'blobdownload' messages from the injected JS.
|
||||
val xwvMessageHandler: (String, JSONObject) -> Unit = handler@{ type, payload ->
|
||||
android.util.Log.d("XWV", "xwvMessage type=$type, payload=${payload.toString().take(200)}")
|
||||
when (type) {
|
||||
"download" -> {
|
||||
val url = payload.optString("url").takeIf { it.isNotBlank() } ?: return@handler
|
||||
@ -267,19 +283,26 @@ fun XWebViewView(
|
||||
"blobdownload" -> {
|
||||
val url = payload.optString("url")
|
||||
val filename = payload.optString("filename").takeIf { it.isNotBlank() } ?: "download.bin"
|
||||
val b64 = payload.optString("data").takeIf { it.isNotBlank() } ?: return@handler
|
||||
val b64 = payload.optString("data").takeIf { it.isNotBlank() } ?: run {
|
||||
android.util.Log.e("XWV", "blobdownload: empty data")
|
||||
return@handler
|
||||
}
|
||||
android.util.Log.d("XWV", "blobdownload: filename=$filename, b64Len=${b64.length}, dest=${config.downloadDestination}")
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
runCatching {
|
||||
FileSDK.saveBlobDownload(context, b64, filename, config.downloadDestination)
|
||||
}.onSuccess { file ->
|
||||
android.util.Log.d("XWV", "blobdownload saved: ${file.absolutePath}, size=${file.length()}")
|
||||
// For image files, save to the system gallery (相册) so they appear in Photos
|
||||
val savedToGallery = runCatching { FileSDK.saveImageToGallery(context, file) }.getOrDefault(false)
|
||||
android.util.Log.d("XWV", "blobdownload savedToGallery=$savedToGallery")
|
||||
withContext(Dispatchers.Main) {
|
||||
dispatchDownloadEvent("__xwvDownloadDone", url, ",success:true")
|
||||
// Only open with file viewer when not saved to gallery (e.g. zip, docx)
|
||||
if (!savedToGallery) FileSDK.openFile(context, file)
|
||||
}
|
||||
}.onFailure { e ->
|
||||
android.util.Log.e("XWV", "blobdownload FAILED", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
dispatchDownloadEvent("__xwvDownloadDone", url, ",success:false,error:'${e.message?.escapeJs()}'")
|
||||
}
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户