安卓程序上传文件到java服务器
主要思路:
将文件转换成Base64字符串,通过Http请求发送到服务器,在服务器端再进行转码,将Base64转换成
文件流
1 APP端
1 先通过Intent获取手机图库里的图片
private static final int CODE_REQUEST_IMG = 1;
private static final String IMG_TYPE = "image/*";
Intent intent4chooseFromFile = new Intent(Intent.ACTION_GET_CONTENT);
intent4chooseFromFile.setType(IMG_TYPE);
startActivityForResult(intent4chooseFromFile, CODE_REQUEST_IMG);
// requestCode起到一个标识符的作用,
// 在callback中可以根据requestCode来判断是返回的哪一个getContent的请求
// 比如很多程序获取图片,都是两个选择:从相机||从相册,这里只写一个做示例
2 这里就是根据请求码来决定下一步操作的示例:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CODE_REQUEST_IMG:
handleChooseAImgResult(resultCode, data);
break;
case CODE_TAKE_A_PHOTO:
handleTakeAPhotoResult(resultCode, data);
break;
default:
break;
}
};
3 然后是handleChooseAImgResult()方法的具体实现:
/**
* @param resultCode
* @param data
*/
private void handleChooseAImgResult(int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
Log.i("CHOOSE IMAGE", "no pic choosed");
return;
} else {
Uri uri = data.getData();
try {
bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(uri));
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
// 暂时设置在imageview上,这里不是重点
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 这个方法是重点,根据uri获取到图片在SDCARD中的实际位置
String path = getImgPathFromContentUri(getApplicationContext(), uri);
Log.i("path", path);
triggerUpload(path);
}
}
4 getImgPathFronContentUri()方法的具体实现:
/**
*
* @param context
* @param uri
* @return image path
*/
private String getImgPathFromContentUri(Context context, Uri uri) {
Cursor cursor = null;
String path = "";
String[] proj = new String[] { MediaStore.Images.Media.DATA };
try {
cursor = context.getContentResolver().query(uri, proj, null, null,
null);
if (cursor != null && cursor.moveToFirst()) {
path = cursor.getString(0);
}
} finally {
cursor.close();
}
return path;
}
5 获取到图片位置之后,就可以进行上传操作了。
如果对于contentprovider这一块操作不熟悉,在学习中可以直接使将文件路径hardcode成一个固定的路径。
url是:
private static final String URL = "http://192.168.1.102:8080/imageReceiver/ImageReceiverServlet";
其中:
1 http://192.168.1.102:8080是本机服务器的地址
2 imageReceiver是server端的javaweb工程名
3 ImageReceiverServlet是server端的servlet路径
上传
private void triggerUpload(final String imagePath) {
StringRequest stringRequest = new StringRequest(Method.POST, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// 在这里接收到服务器返回的消息
Log.i("TAG", response);
if (response.equals("success")) {
Message message = Message.obtain();
message.what = UPLOAD_SUCEESS;
handler.sendMessage(message);
} else {
Message message = Message.obtain();
message.what = UPLOAD_FAILURE;
handler.sendMessage(message);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// 错误处理
Log.i("TAG", error.getMessage(), error);
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
// 在这里设置POST请求的参数
// 因为POST请求和GET请求的结构格式不一样
// 所以服务器端需要用DoPost()方法处理这个请求而不能用DoGet()方法
HashMap<String, String> params = new HashMap<String, String>();
params.put("image", mEncode(imagePath));
params.put("userId", "123");
return params;
}
};
// 设置一个较大的超时的时间,因为上传文件比较耗费时间
stringRequest.setRetryPolicy(new DefaultRetryPolicy(30000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
mQueue.add(stringRequest);
}
6 这里用到的操作网络的jar包是volley,在onCreate()方法中将请求队列初始化:
mQueue = Volley.newRequestQueue(MainActivity.this);
在设置参数的时候:
params.put(“image”, mEncode(imagePath));
7 直接将Base64编码放进参数里,下面是mEncode()方法的具体实现:
// 1 将文件封装成inputStream
// 2 读取inputStream到byteArrayOutputStream中
// 3 通过 byteArrayOutputStream.toByteArray()把流转化成byte数组
// 4 将byte数组转换成Base64对象 并且返回
public String mEncode(String filename) {
int bytesRead;
byte[] bytes = null;
byte[] buffer = new byte[8192]; // 缓冲区
InputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
inputStream = new FileInputStream(filename);
byteArrayOutputStream = new ByteArrayOutputStream();
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
bytes = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
通过
mQueue.add(stringRequest);
8 将请求加入队列之后,后台会发送请求并且等待结果,handler对于返回结果的处理:
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPLOAD_SUCEESS:
Toast.makeText(MainActivity.this, "upload success !",
Toast.LENGTH_SHORT).show();
break;
case UPLOAD_FAILURE:
Toast.makeText(MainActivity.this, "upload failure !",
Toast.LENGTH_SHORT).show();
break;
default:
break;
}
};
};
APP端的代码到这里结束,接下来是服务器端的代码
2 server端
1 接收文件的servlet:
private String result;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html;charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
String imageBase64Code = req.getParameter("image");
if (ImageHeler.convertCode2Image(imageBase64Code)) {
result = "success";
} else {
result = "failure";
}
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.println(result);// 将结果输出给APP端
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
2 ImageHelper的实现:
public class ImageHeler {
public static boolean convertCode2Image(String imageBase64Code) {
boolean isSuccess = false;
try {
// Converting a Base64 String into Image byte array
byte[] imageByteArray = decodeImage(imageBase64Code);
// Write a image byte array into file system
FileOutputStream imageOutFile = new FileOutputStream(
"E:\\hardwork\\" + GTDateUtil.getCurrentStringDateAndTime()
+ ".jpg");
imageOutFile.write(imageByteArray);
imageOutFile.close();
isSuccess = true;
} catch (FileNotFoundException e) {
System.out.println("Image not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while reading the Image " + ioe);
}
return isSuccess;
}
/**
* Decodes the base64 string into byte array
*
* @param imageDataString
* - a {@link java.lang.String}
* @return byte array
*/
public static byte[] decodeImage(String imageDataString) {
return Base64.decodeBase64(imageDataString);
}
}
3 用日期来给图片命名:
dateAntTimeFormat = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
public static String getCurrentStringDateAndTime() {
return dateAntTimeFormat.format(calendar.getTime());
}
4 web.xml的配置:
<servlet>
<servlet-name>ImageReceiverServlet</servlet-name>
<servlet-class>com.imagehelper.ImageReceiverServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageReceiverServlet</servlet-name>
<url-pattern>/ImageReceiverServlet</url-pattern>
</servlet-mapping>