您的位置:首页 > 移动开发 > Android开发

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

2017-04-01 22:31 579 查看
最近比较坑爹,公司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

代码地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: