想必大家都在android中或多或少的使用过XUtils框架了吧,今天我们通过他来实现一个照片上传的Demo,希望能够对大家有帮助,下一篇再从源码角度来分析下XUtils的HttpUtils是怎么一个执行流程的;
先上执行效果图:
客户端实现:
首先来看布局文件:
1
2
3
4
5
6
7
8
|
<relativelayout android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
android:paddingbottom=
"@dimen/activity_vertical_margin"
android:paddingleft=
"@dimen/activity_horizontal_margin"
android:paddingright=
"@dimen/activity_horizontal_margin"
android:paddingtop=
"@dimen/activity_vertical_margin"
tools:context=
".MainActivity"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
>
<linearlayout android:id=
"@+id/top"
android:layout_height=
"wrap_content"
android:layout_width=
"wrap_content"
><button android:id=
"@+id/upload_image"
android:layout_height=
"wrap_content"
android:layout_width=
"wrap_content"
android:text=
"上传图片"
>
<imageview android:id=
"@+id/imageView"
android:layout_below=
"@id/top"
android:layout_centerinparent=
"true"
android:layout_height=
"wrap_content"
android:layout_width=
"wrap_content"
>
</imageview></button></linearlayout></relativelayout>
|
接下来是MainActivity,直接看onCreate方法:
1
2
3
4
5
6
7
8
|
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
httpUtils =
new
HttpUtils(
100000
);
httpUtils.configCurrentHttpCacheExpiry(
5000
);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
/**
* 初始化view控件
*/
public
void
initView()
{
uploadImageBt = (Button) findViewById(R.id.upload_image);
imageView = (ImageView)findViewById(R.id.imageView);
uploadImageBt.setOnClickListener(
this
);
progressDialog = getProgressDialog();
//获得进度条
dialogListener =
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
switch
(which) {
case
0
:
tempFile =
new
File(Environment.getExternalStorageDirectory(),getPhotoFileName());
//调用系统拍照
startCamera(dialog);
break
;
case
1
:
//打开系统图库
startWall(dialog);
break
;
default
:
break
;
}
}
};
mHandler =
new
Handler(){
@Override
public
void
handleMessage(Message msg) {
if
(msg.arg1 >
0
)
progressDialog.setProgress(msg.arg1);
//更新进度条
}
};
}
|
首先第9行获得一个ProgressDialog对象,第10行为选择对话框绑定点击监听事件,用来提示用户是通过拍照获得照片还是从图库获得,这个对象的定义如下:
1
2
3
4
5
6
7
8
9
10
11
|
/**
* 显示选择图片来源的dialog(来自拍照还是本地图库)
* @param title
* @param items
*/
public
void
showDialog(String title,String[] items)
{
AlertDialog.Builder dialog =
new
AlertDialog.Builder(
this
).setTitle(title).setItems(items, dialogListener);
//显示dialog
dialog.show();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* 调用相机来照相
* @param dialog
*/
public
void
startCamera(DialogInterface dialog)
{
dialog.dismiss();
//首先隐藏选择照片来源的dialog
//调用系统的拍照功能
Intent intent =
new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(
"camerasensortype"
,
2
);
//调用前置摄像头
intent.putExtra(
"autofocus"
,
true
);
//进行自动对焦操作
intent.putExtra(
"fullScreen"
,
false
);
//设置全屏
intent.putExtra(
"showActionIcons"
,
false
);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
//指定调用相机之后所拍照存储到的位置
startActivityForResult(intent, PHOTO_CAMERA);
}
|
如果选择的是相册的话,则通过调用startWall方法来获得SD上面照片:
1
2
3
4
5
6
7
8
9
10
11
|
/**
* 打开系统图库
* @param dialog
*/
public
void
startWall(DialogInterface dialog)
{
dialog.dismiss();
//设置隐藏dialog
Intent intent =
new
Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*"
);
startActivityForResult(intent, PHOTO_WALL);
}
|
接下来我们看看不同的返回标志各自所执行的到底是什么内容呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@Override
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
super
.onActivityResult(requestCode, resultCode, data);
switch
(requestCode) {
case
PHOTO_CAMERA:
//表示从相机获得的照片,需要进行裁剪
startPhotoCut(Uri.fromFile(tempFile),
300
,
true
);
break
;
case
PHOTO_WALL:
if
(
null
!= data)
startPhotoCut(data.getData(),
300
,
false
);
break
;
case
PHOTO_STORE:
if
(
null
!= data)
{
setPictureToImageView(data,
true
);
}
break
;
case
PHOTO_NOT_STORE:
if
(
null
!= data)
{
setPictureToImageView(data,
false
);
}
break
;
default
:
break
;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
* 将图片裁剪到指定大小
* @param uri
* @param size
* @param flag
*/
public
void
startPhotoCut(Uri uri,
int
size,
boolean
flag)
{
Intent intent =
new
Intent(
"com.android.camera.action.CROP"
);
intent.setDataAndType(uri,
"image/*"
);
intent.putExtra(
"crop"
,
true
);
//设置Intent中的view是可以裁剪的
//设置宽高比
intent.putExtra(
"aspectX"
,
1
);
intent.putExtra(
"aspectY"
,
1
);
//设置裁剪图片的宽高
intent.putExtra(
"outputX"
, size);
intent.putExtra(
"outputY"
, size);
//设置是否返回数据
intent.putExtra(
"return-data"
,
true
);
if
(flag ==
true
)
startActivityForResult(intent, PHOTO_STORE);
else
{
tempIntent = intent;
try
{
startActivityForResult(tempIntent, PHOTO_NOT_STORE);
System.out.println(
"haha"
);
}
catch
(Exception e) {
System.out.println(e.toString());
}
}
}
|
那么对于PHOTO_WALL标志,如果选择的图片不为空的话,则执行startPhotoCut方法,同样也进行裁剪;
对于PHOTO_NOT_STORE和PHOTO_STORE标志,他们都会执行setPictureToImageView方法,所以我们直接看他的代码就可以了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
/**
* 将图片显示到ImageView上面
* @param data
* @param flag 表示如果是拍照获得的照片的话则是true,如果是从系统选择的照片的话就是false
*/
public
void
setPictureToImageView(Intent data,
boolean
flag)
{
Bundle bundle = data.getExtras();
if
(
null
!= bundle)
{
Bitmap bitmap = bundle.getParcelable(
"data"
);
imageView.setImageBitmap(bitmap);
//将图片显示到ImageView上面
//上传图片到服务器
if
(flag ==
false
)
{
//需要首先修改tempFile的值
String path = getSelectPhotoPath(tempIntent);
System.out.println(
"path: "
+path);
tempFile =
new
File(path);
//uploadPicture();
//上传图片
UploadThread thread =
new
UploadThread();
thread.start();
}
else
{
//uploadPicture();
//上传图片
UploadThread thread =
new
UploadThread();
thread.start();
}
if
(flag ==
true
)
savePictureToSD(bitmap);
//保存图片到sd卡上面
}
}
|
1
2
3
4
5
6
7
|
class
UploadThread
extends
Thread
{
@Override
public
void
run() {
uploadPicture();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/**
* 上传图片到数据库
*/
public
void
uploadPicture()
{
RequestParams params =
new
RequestParams();
params.addBodyParameter(
"msg"
,tempFile.getAbsolutePath());
params.addBodyParameter(tempFile.getPath().replace(
"/"
,
""
), tempFile);
httpUtils.send(HttpMethod.POST, url,params,
new
RequestCallBack<string>() {
@Override
public
void
onStart() {
progressDialog.show();
//显示进度条
}
@Override
public
void
onFailure(HttpException arg0, String arg1) {
System.out.println(
"上传失败"
);
System.out.println(arg0.toString());
//上传失败之后隐藏进度条
progressDialog.dismiss();
}
@Override
public
void
onLoading(
long
total,
long
current,
boolean
isUploading) {
System.out.println(
"current/total: "
+current+
"/"
+total);
int
process =
0
;
if
(total !=
0
)
{
process = (
int
)(current/(total/
100
));
}
Message message =
new
Message();
message.arg1 = process;
mHandler.sendMessage(message);
super
.onLoading(total, current, isUploading);
}
@Override
public
void
onSuccess(ResponseInfo<string> arg0) {
System.out.println(
"上传成功"
);
//上传成功之后隐藏进度条
progressDialog.dismiss();
}
});
}</string></string>
|
最后就只剩下保存图片到SD卡的操作了,这个比较简单,就只是简单的文件存储操作了,只不过路径是SD卡而已:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
* 将图片保存到SD卡上面
* @param bitmap
*/
public
void
savePictureToSD(Bitmap bitmap)
{
ByteArrayOutputStream baos =
new
ByteArrayOutputStream();
FileOutputStream fos =
null
;
bitmap.compress(Bitmap.CompressFormat.JPEG,
100
, baos);
//第2个参数表示压缩率,100表示不压缩
try
{
fos =
new
FileOutputStream(tempFile);
fos.write(baos.toByteArray());
fos.flush();
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
try
{
if
(
null
!= baos)
{
baos.close();
baos =
null
;
}
if
(
null
!= fos)
{
fos.close();
fos =
null
;
}
}
catch
(Exception e2) {
}
}
}
|
服务器端:
代码比较少,直接copy出来了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
class
UploadServlet
extends
HttpServlet {
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
doPost(request, response);
}
public
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
request.setCharacterEncoding(
"utf-8"
);
response.setCharacterEncoding(
"utf-8"
);
response.setContentType(
"text/html,charset=utf-8"
);
SmartUpload smartUpload =
new
SmartUpload();
String msg=
null
;
try
{
smartUpload.initialize(
this
.getServletConfig(), request, response);
smartUpload.upload();
msg = smartUpload.getRequest().getParameter(
"msg"
);
System.out.println(smartUpload.getFiles().getCount());
com.jspsmart.upload.File smartFile = smartUpload.getFiles().getFile(
0
);
if
(!smartFile.isMissing()) {
String saveFileName = getServletContext().getRealPath(
"/"
)+
"images\\"
+ smartFile.getFileName();
System.out.println(saveFileName);
smartFile.saveAs(saveFileName, SmartUpload.SAVE_PHYSICAL);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
|
最主要是doPost方法了,本实例采用的是SmartUpload的方式来实现文件上传操作的,当然你也可以采用别的方法,至于jar包等会源码下载链接的工程里面就有啦,第18行首先对SmartUpload进行初始化,接着调用upload方法准备上传,第22行获得客户端上传文件的第一个文件,从这里我们也可以看出来SmartUpload是支持多文件上传的,接着第23行判断这个文件是否存在,24行生成存放文件的路径,26行进行文件的存储操作,注意SmartUpload.SAVE_PHYSICAL的意思指的是绝对路径,因此你的文件存储路径必须是全路径,这样服务器端代码讲解结束,是不是很简单呀,提醒一下web.xml的配置,我的配置如下:
1
2
3
4
5
6
7
8
9
10
11
|
<!--?xml version=
"1.0"
encoding=
"UTF-8"
?-->
<web-app id=
"WebApp_ID"
version=
"2.5"
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemalocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
>
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-
class
>com.hzw.servlet.UploadServlet</servlet-
class
>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
</web-app>
|
基本上讲解结束啦,记得在客户端里面别忘记添加网络访问和SD卡访问权限哈:
本文 由微信妈妈ontaobao.cn(公众号买卖) 转载文章来源 http://www.2cto.com/kf/201606/516043.html