我一直在努力从WebView上传文件。我在谷歌上搜索并实施了所有建议的解决方案(例如这篇SO帖子),但没有一个可行。

我有一个HTML页面与以下代码上传文件。

<form method="POST" enctype="multipart/form-data">
  File to upload: <input type="file" name="uploadfile">&nbsp;&nbsp;
  <input type="submit" value="Press to Upload..."> to upload the file!
</form>

它在桌面浏览器如Firefox和内置浏览器中运行良好 的模拟器/ AVD,即,当我点击“浏览…”按钮渲染 元素,浏览器打开一个对话框 框,在那里我可以选择一个文件上传。

然而,在android 3.0模拟器/ AVD中,当我点击“选择” 文件”,什么都没有发生,没有文件对话框被打开!


当前回答

在棒棒糖5.0中,谷歌添加了一个官方方法WebChromeClient.onShowFileChooser。它们甚至提供了一种自动生成文件选择器意图的方法,以便它使用输入接受mime类型。

public class MyWebChromeClient extends WebChromeClient {
        // reference to activity instance. May be unnecessary if your web chrome client is member class.
    private MyActivity activity;

    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // make sure there is no existing message
        if (myActivity.uploadMessage != null) {
            myActivity.uploadMessage.onReceiveValue(null);
            myActivity.uploadMessage = null;
        }

        myActivity.uploadMessage = filePathCallback;

        Intent intent = fileChooserParams.createIntent();
        try {
            myActivity.startActivityForResult(intent, MyActivity.REQUEST_SELECT_FILE);
        } catch (ActivityNotFoundException e) {
            myActivity.uploadMessage = null;
            Toast.makeText(myActivity, "Cannot open file chooser", Toast.LENGTH_LONG).show();
            return false;
        }

        return true;
    }
}


public class MyActivity extends ... {
    public static final int REQUEST_SELECT_FILE = 100;
    public ValueCallback<Uri[]> uploadMessage;

    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if (requestCode == REQUEST_SELECT_FILE) {
                if (uploadMessage == null) return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                uploadMessage = null;
            }
        }
    }
}

对于KitKat之前的Android版本,其他答案中提到的私有方法是有效的。我还没有为KitKat(4.4)找到一个好的解决方案。

其他回答

在棒棒糖5.0中,谷歌添加了一个官方方法WebChromeClient.onShowFileChooser。它们甚至提供了一种自动生成文件选择器意图的方法,以便它使用输入接受mime类型。

public class MyWebChromeClient extends WebChromeClient {
        // reference to activity instance. May be unnecessary if your web chrome client is member class.
    private MyActivity activity;

    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // make sure there is no existing message
        if (myActivity.uploadMessage != null) {
            myActivity.uploadMessage.onReceiveValue(null);
            myActivity.uploadMessage = null;
        }

        myActivity.uploadMessage = filePathCallback;

        Intent intent = fileChooserParams.createIntent();
        try {
            myActivity.startActivityForResult(intent, MyActivity.REQUEST_SELECT_FILE);
        } catch (ActivityNotFoundException e) {
            myActivity.uploadMessage = null;
            Toast.makeText(myActivity, "Cannot open file chooser", Toast.LENGTH_LONG).show();
            return false;
        }

        return true;
    }
}


public class MyActivity extends ... {
    public static final int REQUEST_SELECT_FILE = 100;
    public ValueCallback<Uri[]> uploadMessage;

    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if (requestCode == REQUEST_SELECT_FILE) {
                if (uploadMessage == null) return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                uploadMessage = null;
            }
        }
    }
}

对于KitKat之前的Android版本,其他答案中提到的私有方法是有效的。我还没有为KitKat(4.4)找到一个好的解决方案。

我找到了一个适合我的解决方案!在proguard-android.txt文件中增加一条规则:

-keepclassmembers class * extends android.webkit.WebChromeClient {
     public void openFileChooser(...);
}

Android 8的Kotlin解决方案:

private var mUploadMessage: ValueCallback<Uri>? = null
private var uploadMessage: ValueCallback<Array<Uri>>? = null

常量:

const val FILECHOOSER_RESULTCODE = 1
const val REQUEST_SELECT_FILE = 100

WebView设置:

webView.webChromeClient = object : WebChromeClient() {
        override fun onPermissionRequest(request: PermissionRequest?) {
            Log.d("MainActivity", "onPermissionRequest")
            requestPermission(request)
        }


        // For Android 3.0+
        fun openFileChooser(uploadMsg: ValueCallback<*>, acceptType: String) {
            mUploadMessage = uploadMsg as ValueCallback<Uri>
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "*/*"
            this@MainActivity.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE)
        }

        //For Android 4.1
        fun openFileChooser(uploadMsg: ValueCallback<Uri>, acceptType: String, capture: String) {
            mUploadMessage = uploadMsg
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "image/*"
            this@MainActivity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)

        }

        protected fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
            mUploadMessage = uploadMsg
            val intent = Intent(Intent.ACTION_GET_CONTENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            intent.type = "*/*"
            startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE)
        }

        override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
            uploadMessage?.onReceiveValue(null)
            uploadMessage = null

            uploadMessage = filePathCallback

            val intent = fileChooserParams!!.createIntent()
            try {
                startActivityForResult(intent, REQUEST_SELECT_FILE)
            } catch (e: ActivityNotFoundException) {
                uploadMessage = null
                Toast.makeText(applicationContext, "Cannot Open File Chooser", Toast.LENGTH_LONG).show()
                return false
            }

            return true
        }

    }

onactivityresult部分:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (requestCode === REQUEST_SELECT_FILE) {
            if (uploadMessage == null)
                return
            print("result code = " + resultCode)
            var results: Array<Uri>? = WebChromeClient.FileChooserParams.parseResult(resultCode, data)
            uploadMessage?.onReceiveValue(results)
            uploadMessage = null
        }
    } else if (requestCode === FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return
        // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
        // Use RESULT_OK only if you're implementing WebView inside an Activity
        val result = if (intent == null || resultCode !== RESULT_OK) null else intent.data
        mUploadMessage?.onReceiveValue(result)
        mUploadMessage = null
    } else
        Toast.makeText(applicationContext, "Failed to Upload Image", Toast.LENGTH_LONG).show()
}

请注意,我们的意图变量称为“数据”。

我是android的新手,在这方面也很吃力。根据谷歌参考指南WebView。

默认情况下,WebView不提供类似浏览器的小部件 启用JavaScript和网页错误被忽略。如果你的目标是 只是显示一些HTML作为你的UI的一部分,这可能是好的; 除了阅读,用户不需要与网页进行交互, 网页也不需要与用户交互。如果你真的 想要一个成熟的web浏览器,那么您可能需要调用 浏览器应用程序的URL意图,而不是显示它与 WebView。

我在mainactivity .java中执行的示例代码。

 Uri uri = Uri.parse("https://www.example.com");
 Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 startActivity(intent);

Excuted

package example.com.myapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.content.Intent;
import android.net.Uri;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Uri uri = Uri.parse("http://www.example.com/");
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
        getSupportActionBar().hide();
    }}

你访问过这个链接吗? http://groups.google.com/group/android-developers/browse_thread/thread/dcaf8b2fdd8a90c4/62d5e2ffef31ebdb

http://moazzam-khan.com/blog/?tag=android-upload-file

http://evgenyg.wordpress.com/2010/05/01/uploading-files-multipart-post-apache/

通过javalib Apache Commons上传文件的简明示例

我想你会从中得到帮助的