android WebView上传文件到服务器[android+server代码]

来源:互联网 发布:苹果如何清理游戏数据 编辑:程序博客网 时间:2024/05/18 00:59

最近比较坑爹,公司app部分页面要转H5,美其名曰称之为节约人力成本,无奈,我们就从后台PHP,JQuery从零开始学起。项目中遇到这么一个问题:要从android的WebView中上传用户头像到服务器,当初感觉蛮简单的,就没怎么注意,没想到一道道大坑摆在我面前,特此记录一下。

前端界面蛮丑的,这么就不说,基本上就像下图一样:
这里写图片描述

这里的加号图片,主要是美化上传用的,它还有一个作用就是图片预览功能,基本上代码如下:

        $("#img").on("click", function () {            $("#file").click();        });

就是讲img的点击事件,强制转化给file的点击事件,就是我们选择文件的事件,还是比较聪明的。

页面我就先不做优化了,采用的是ajax后台上传的,部分代码如下【全部代码将会最后给出】:

  $("#upload").on("click",function () {            var form  = new FormData(document.getElementById("form")) ;            $.ajax({                url: $("#upload").attr("data_url"),                data: form,                type: "post",                cache:false,                contentType:false,                processData:false,                dataType: "json",                success: function (data) {                    console.log("-->>" + data.code + "...." + data.message);                    $("#id_msg").html(data.code + "------" + data.message);                },                error: function () {                    console.log("error--------->>");                    $("#id_msg").html("upload error");                }            });        });

我们采用了FormData元素作为上传对象,具体参数意义,可参见这篇文章,基本上写得非常清楚了,这也解释了我第一次将表单序列化上传时,为什么会失败的原因了。

再就是服务器代码了,我采用的是thinkPHP3.2.3的方式,没有放开扯,毕竟这个还是比较简单的,不要问我为啥用java去写,当然我也是可以的,原因是我的Tomcat有些启动问题,这里不就扯多了,部分关键代码如下:

$upload = new Upload(); // 实例化上传类        $upload->maxSize = 5242880; // 设置附件上传大小        $upload->exts = array('jpg', 'gif', 'png', 'jpeg'); // 设置附件上传类型        $upload->rootPath = "./"; // 设置附件上传根目录        $upload->savePath = ''; // 设置附件上传(子)目录        $upload->saveName = array('date', '_ymdHis' . rand(100, 999));        $upload->subName = array('date', 'Ymd'); //子目录创建方式,[0]-函数名,[1]-参数,多个参数使用数组        $info = $upload->upload();        $arr = array();        if ($info) {            $arr["code"] = 200;            $arr["message"] = "success";        } else {            $arr["code"] = -1;            $arr["message"] = "error";        }        exit(json_encode($arr));

当我屁颠屁颠的写完了这些代码,android直接写个webView加载我的本地网页,我想这不会这么简单吧,话刚说话,webview进入加载页面之后,效果出现了,我点添加的页面不动了,使用IOS测试,看下图:

这里写图片描述

IOS是有效果的,看来使我们的andorid中的webView存在问题啊,好吧,查查哪里出了问题吧,google之后,发现我们的webView对应的webChromeClient中有个这个方法:
这里写图片描述

告诉我们的client,来展示一个图片选择器,返回值如果是false,就执行默认操作;如果返回值是true,那么ValueCallback将会被调用,那好吧,那只有自己重写这个onShowFileChooser方法了,先设置一个回调,然后返回值设置为true:

    @Override    public boolean onShowFileChooser(WebView webView,            ValueCallback<Uri[]> filePathCallback,            FileChooserParams fileChooserParams) {          if (webCall != null)              webCall.fileChose5(filePathCallback);          return true ;    }    public interface WebCall {          //android version < 5.0        void fileChose(ValueCallback<Uri> uploadMsg);          //android version > 5.0          void fileChose5(ValueCallback<Uri[]> uploadMsg);    }  

设置webView的Client方法:

        MyWebChromeClient client = new MyWebChromeClient();        client.setWebCall(this);        mWebView.setWebChromeClient(client);

在Android代码中回调该方法:

 @Override    public void fileChose(ValueCallback<Uri> uploadMsg) {        openFileChooserImpl(uploadMsg);    }    @Override    public void fileChose5(ValueCallback<Uri[]> uploadMsg) {        openFileChooserImplForAndroid5(uploadMsg);    }    //andoird版本小于5.0的实现    private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) {        mUploadMessage = uploadMsg;        Intent i = new Intent(Intent.ACTION_GET_CONTENT);        i.addCategory(Intent.CATEGORY_OPENABLE);        i.setType("image/*");        startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);    }   //android版本大约5.0的实现    private void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg) {        mUploadMessageForAndroid5 = uploadMsg;        Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);        contentSelectionIntent.setType("image/*");        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);        chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");        startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);    }

然后设置其onActivityForResult方法:

    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {        if (requestCode == FILECHOOSER_RESULTCODE) {            if (null == mUploadMessage) return;            Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();            mUploadMessage.onReceiveValue(result);            mUploadMessage = null;        } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) {            if (null == mUploadMessageForAndroid5) return;            Uri result = (intent == null || resultCode != RESULT_OK) ? null : intent.getData();            if (result != null) {                mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});            } else {                mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});            }            mUploadMessageForAndroid5 = null;        }    }

设置之后,编译运行代码,点击图片,我们想要的file chooser就出现了:

这里写图片描述

选择一张图片,然后上传:
这里写图片描述

200表示上传成功了,我们可以上服务器看一下图片:
这里写图片描述

嗯,我看到了我们上传的图片了,是的,android通过webview上传图片成功了,我特么搞了好几天你懂么??太多的问题不是很懂啊,不是很懂啊,中间遇到很多坑,刚开始以为是h5代码兼容性问题,一直在h5那里找错误,可是没想到居然是webview的client问题,好吧,再次记录一下。

感谢:
http://blog.csdn.net/qq_33556185/article/details/51086114
http://blog.csdn.net/atangsir/article/details/51388662

代码地址

1 0
原创粉丝点击