You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView 文件上传功能失效问题求助

解决Android WebView文件上传失效的问题

嘿,我一眼就看出问题所在啦!你的WebView代码里没有处理文件上传的Intent请求——默认情况下,Android WebView不会自动弹出文件选择器,特别是从KitKat(API 19)开始,我们得手动实现相关回调才能让文件上传功能正常工作。

下面是具体的修复步骤和完整代码:

1. 核心问题分析

你的代码只设置了WebViewClient(负责页面导航逻辑),但文件上传需要依赖WebChromeClient来处理浏览器发起的文件选择请求。从Android 5.0(API 21)开始,官方推荐使用onShowFileChooser方法,同时我们也要兼容旧版本的openFileChooser方法来覆盖更多系统版本。

2. 修复后的完整代码

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient.FileChooserParams;

public class MainActivity extends AppCompatActivity {
    private WebView myWebView;
    // 用于接收文件选择结果的回调对象
    private ValueCallback<Uri[]> filePathCallback;
    private static final int FILE_CHOOSER_REQUEST_CODE = 1000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myWebView = findViewById(R.id.webView);
        WebSettings webSettings = myWebView.getSettings();
        
        // 开启JavaScript(你已经完成这一步)
        webSettings.setJavaScriptEnabled(true);
        // 开启文件访问权限,确保WebView能访问本地文件
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        
        myWebView.loadUrl("your domain url");
        myWebView.setWebViewClient(new WebViewClient());
        
        // 关键操作:设置WebChromeClient处理文件上传请求
        myWebView.setWebChromeClient(new WebChromeClient() {
            // Android 5.0+ 版本的文件选择回调
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                // 先释放之前的回调,避免内存泄漏
                if (MainActivity.this.filePathCallback != null) {
                    MainActivity.this.filePathCallback.onReceiveValue(null);
                }
                MainActivity.this.filePathCallback = filePathCallback;
                
                // 启动系统默认的文件选择器
                Intent intent = fileChooserParams.createIntent();
                try {
                    startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
                } catch (Exception e) {
                    MainActivity.this.filePathCallback = null;
                    return false;
                }
                return true;
            }

            // 兼容Android 5.0以下版本的文件选择回调
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                ValueCallback<Uri[]> filePathCallbackWrapper = new ValueCallback<Uri[]>() {
                    @Override
                    public void onReceiveValue(Uri[] uris) {
                        uploadMsg.onReceiveValue(uris != null && uris.length > 0 ? uris[0] : null);
                    }
                };
                openFileChooser(filePathCallbackWrapper, acceptType, capture);
            }
        });
    }

    // 处理文件选择后的返回结果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
            Uri[] results = null;
            // 判断文件选择是否成功
            if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    String dataString = data.getDataString();
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                }
            }
            // 将结果返回给WebView,完成文件上传的触发逻辑
            if (filePathCallback != null) {
                filePathCallback.onReceiveValue(results);
                filePathCallback = null;
            }
        }
    }

    @Override
    public void onBackPressed() {
        if(myWebView.canGoBack()){
            myWebView.goBack();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

3. 额外注意事项

  • 权限配置:在AndroidManifest.xml中添加文件读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • 动态权限申请:如果你的应用目标SDK版本是23及以上,还需要在代码中动态请求READ_EXTERNAL_STORAGE权限,否则文件选择器可能无法正常访问设备存储。

这样修改后,你的WebView就能正常触发文件上传选择器,完美解决KitKat、Lollipop及更高版本的文件上传失效问题啦!

内容的提问来源于stack exchange,提问作者waheed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:24:26