Android 上传图片到JavaWeb服务器
2016-11-27 09:13
477 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[+]
一实现效果
二表单中enctype
1 表单中enctype的作用是什么
2 为什么上传文件要设置enctypemultipartform-data
三服务端fileupload接收文件
使用 fileupload 解析request
获取上传字段
更改文件名称为唯一
生成存储路径
存储文件
响应文件存储地址
四客户端OkHttp上传文件
使用OkHttp上传图片文件
上传图片Task编写
OkHttp上传文件编写
通过Glide加载图片
五客户端上传用户ID及图片
客户端添加参数
2 服务器端接收
六源码及示例
七测试提示
八结语
转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/51453077
本文出自:【Kevin.zhou的博客】
前言:在上一篇博客《Android 拍照、选择图片并裁剪》中主要说明了在Android中图片裁剪的一种方式,当然我们裁剪图片的最终目的是为了上传服务器,最常用的是设置用户头像。即用户在客户端拍照或者选择图片后上传服务器,服务器返回图片在服务器的地址,然后再携带用户信息与头像地址发送请求到服务器修改用户信息。或者上传图片到服务器的时候即携带用户信息,这样一次网略请求就可以搞定了。要根据不同的需求灵活选择合适的方案。在上一篇中有朋友反映写的太复杂,其实只是进行了一些基类的抽取与封装、接口回调的解耦等,是为了使用更简洁方便,该篇博客中会尽量拆分开,方便大家二次封装。
有朋友可能说和上篇博客的效果一样嘛,那我岂不是忽悠大家了。不是的,这里裁剪完之后就进行了上传服务器,然后在将服务器的图片下载后设置给ImageView。
表单中enctype的作用是设置表单的MIME编码。默认情况,这个编码格式是 application/x-www-form-urlencoded,如果在服务器端要通过Request对象来获取相应表单域的值,则应该将enctype属性设置为application/x-www-form-urlencoded值(即默认值,可以不显示设置)。
enctype="multipart/form-data"是上传二进制数据过去,默认的application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据。
因为:设置enctype为multipart/form-data值后,不对字符编码,则数据通过二进制的形式传送到服务器端,这时如果用request是无法直接获取到相应表单的值的,而应该通过stream流对象,将传到服务器端的二进制数据解码,从而读取数据。如果要上传文件的话,是一定要将encotype设置为multipart/form-data的。
所以,如果是在jsp中应这样来写文件上传的表单:
[java]
view plain
copy
print?
DiskFileItemFactory dff = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(dff);
List<FileItem> items = sfu.parseRequest(request);
断点调试图如下:
通过断点调试图,可以看到上传文件封装到FileItem的属性,我们最关心的是fieldName、fileName、以及临时文件tempFile。
[java]
view plain
copy
print?
// 获取上传字段
FileItem fileItem = items.get(0);
[java]
view plain
copy
print?
// 更改文件名为唯一的
String filename = fileItem.getName();
if (filename != null) {
filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
}
[java]
view plain
copy
print?
/**
* 生成UUID
*
* @return UUID
*/
public static String generateGUID() {
return new BigInteger(165, new Random()).toString(36).toUpperCase();
}
[java]
view plain
copy
print?
String storeDirectory = getServletContext().getRealPath("/files/images");
来获取项目下的files/images文件夹,但是如果上传的文件非常多时以后检索该文件夹就比较费时,这里通过文件的哈希来进行二级目录划分,每个目录16个文件夹,这样最多划分出256个文件夹。
[java]
view plain
copy
print?
// 计算文件的存放目录
private String genericPath(String filename, String storeDirectory) {
int hashCode = filename.hashCode();
int dir1 = hashCode&0xf;
int dir2 = (hashCode&0xf0)>>4;
String dir = "/"+dir1+"/"+dir2;
File file = new File(storeDirectory,dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
view plain
copy
print?
fileItem.write(new File(storeDirectory + path, filename));
String filePath = "/files/images" + path + "/" + filename;
view plain
copy
print?
String filePath = "/files/images" + path + "/" + filename;
response.getWriter().write(filePath);
通过以上步骤,就将上传的文件存储到了服务器,并将文件的存储相对项目地址返回。
1、监听裁剪结果
在上一篇《Android
拍照、选择图片并裁剪》中,我们通过设置裁剪图片的监听获取到裁剪后的图片:
[java]
view plain
copy
print?
// 设置裁剪图片结果监听
setOnPictureSelectedListener(new OnPictureSelectedListener() {
@Override
public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
mPictureIv.setImageBitmap(bitmap);
String filePath = fileUri.getEncodedPath();
String imagePath = Uri.decode(filePath);
Toast.makeText(mContext, "图片已经保存到:" + imagePath, Toast.LENGTH_LONG).show();
}
});
我们将裁剪图片结果的监听回调修改如下,即裁剪完成后就上传图片到服务器
[java]
view plain
copy
print?
// 设置裁剪图片结果监听
setOnPictureSelectedListener(new OnPictureSelectedListener() {
@Override
public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
// mPictureIv.setImageBitmap(bitmap);
String filePath = fileUri.getEncodedPath();
final String imagePath = Uri.decode(filePath);
uploadImage(imagePath);
}
});
由于OkHttp虽然有异步网络访问,但是回调还是处在子线程不能修改界面,这里编写一个NetworkTask来进行子线程到主线程的链接。
[java]
view plain
copy
print?
/**
* 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
*/
class NetworkTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return doPost(params[0]);
}
@Override
protected void onPostExecute(String result) {
Log.i(TAG, "服务器响应" + result);
}
}
在NetworkTask中,我们可以看到OkHttp上传的时候只有给它一个要上传文件的路径就可以了,然后返回上传后服务器返回的路径。
OkHttp提供了MultipartBody来进行文件的上传:
[java]
view plain
copy
print?
private String doPost(String imagePath) {
OkHttpClient mOkHttpClient = new OkHttpClient();
String result = "error";
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.addFormDataPart("image", imagePath,
RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
RequestBody requestBody = builder.build();
Request.Builder reqBuilder = new Request.Builder();
Request request = reqBuilder
.url(Constant.BASE_URL + "/uploadimage")
.post(requestBody)
.build();
Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
try{
Response response = mOkHttpClient.newCall(request).execute();
Log.d(TAG, "响应码 " + response.code());
if (response.isSuccessful()) {
String resultValue = response.body().string();
Log.d(TAG, "响应体 " + resultValue);
return resultValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
view plain
copy
print?
/**
* 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
*/
class NetworkTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return doPost(params[0]);
}
@Override
protected void onPostExecute(String result) {
if(!"error".equals(result)) {
Log.i(TAG, "图片地址 " + Constant.BASE_URL + result);
Glide.with(mContext)
.load(Constant.BASE_URL + result)
.into(mPictureIv);
}
}
}
OK,图片加载出来了,来看下我们设置的Log日志:
客户端只需要添加一个用户Id的字段就可以了
[java]
view plain
copy
print?
// 这里演示添加用户ID
builder.addFormDataPart("userId", "20160519142605");
整体代码如下:
[java]
view plain
copy
print?
private String doPost(String imagePath) {
OkHttpClient mOkHttpClient = new OkHttpClient();
String result = "error";
MultipartBody.Builder builder = new MultipartBody.Builder();
// 这里演示添加用户ID
builder.addFormDataPart("userId", "20160519142605");
builder.addFormDataPart("image", imagePath,
RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
RequestBody requestBody = builder.build();
Request.Builder reqBuilder = new Request.Builder();
Request request = reqBuilder
.url(Constant.BASE_URL + "/uploadimage")
.post(requestBody)
.build();
Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
try{
Response response = mOkHttpClient.newCall(request).execute();
Log.d(TAG, "响应码 " + response.code());
if (response.isSuccessful()) {
String resultValue = response.body().string();
Log.d(TAG, "响应体 " + resultValue);
return resultValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
[java]
view plain
copy
print?
// 修改用户的图片
private void changeUserImage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String message = "";
try{
DiskFileItemFactory dff = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(dff);
List<FileItem> items = sfu.parseRequest(request);
for(FileItem item:items){
if(item.isFormField()){
//普通表单
String fieldName = item.getFieldName();
String fieldValue = item.getString();
System.out.println("name="+fieldName + ", value="+ fieldValue);
} else {// 获取上传字段
// 更改文件名为唯一的
String filename = item.getName();
if (filename != null) {
filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
}
// 生成存储路径
String storeDirectory = getServletContext().getRealPath("/files/images");
File file = new File(storeDirectory);
if (!file.exists()) {
file.mkdir();
}
String path = genericPath(filename, storeDirectory);
// 处理文件的上传
try {
item.write(new File(storeDirectory + path, filename));
String filePath = "/files/images" + path + "/" + filename;
System.out.println("filePath="+filePath);
message = filePath;
} catch (Exception e) {
message = "上传图片失败";
}
}
}
} catch (Exception e) {
e.printStackTrace();
message = "上传图片失败";
} finally {
response.getWriter().write(message);
}
}
当然这里只是演示如何接收用户ID以及图片,具体的业务要具体实现。控制台打印结果如下:
通过上一篇博客《Android
拍照、选择图片并裁剪》以及该篇《Android 上传图片到JavaWeb服务器》,相信朋友们对于裁剪图片并上传服务器有了大致的了解,当然实现方式只是一种,主要是理清思路并灵活运用。
目录(?)[+]
一实现效果
二表单中enctype
1 表单中enctype的作用是什么
2 为什么上传文件要设置enctypemultipartform-data
三服务端fileupload接收文件
使用 fileupload 解析request
获取上传字段
更改文件名称为唯一
生成存储路径
存储文件
响应文件存储地址
四客户端OkHttp上传文件
使用OkHttp上传图片文件
上传图片Task编写
OkHttp上传文件编写
通过Glide加载图片
五客户端上传用户ID及图片
客户端添加参数
2 服务器端接收
六源码及示例
七测试提示
八结语
转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/51453077
本文出自:【Kevin.zhou的博客】
前言:在上一篇博客《Android 拍照、选择图片并裁剪》中主要说明了在Android中图片裁剪的一种方式,当然我们裁剪图片的最终目的是为了上传服务器,最常用的是设置用户头像。即用户在客户端拍照或者选择图片后上传服务器,服务器返回图片在服务器的地址,然后再携带用户信息与头像地址发送请求到服务器修改用户信息。或者上传图片到服务器的时候即携带用户信息,这样一次网略请求就可以搞定了。要根据不同的需求灵活选择合适的方案。在上一篇中有朋友反映写的太复杂,其实只是进行了一些基类的抽取与封装、接口回调的解耦等,是为了使用更简洁方便,该篇博客中会尽量拆分开,方便大家二次封装。
一、实现效果
按照之前博客风格,首先看下实现效果。有朋友可能说和上篇博客的效果一样嘛,那我岂不是忽悠大家了。不是的,这里裁剪完之后就进行了上传服务器,然后在将服务器的图片下载后设置给ImageView。
二、表单中enctype
1. 表单中enctype的作用是什么?
表单中enctype的作用是设置表单的MIME编码。默认情况,这个编码格式是 application/x-www-form-urlencoded,如果在服务器端要通过Request对象来获取相应表单域的值,则应该将enctype属性设置为application/x-www-form-urlencoded值(即默认值,可以不显示设置)。
enctype="multipart/form-data"是上传二进制数据过去,默认的application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据。
2. 为什么上传文件要设置enctype="multipart/form-data"?
因为:设置enctype为multipart/form-data值后,不对字符编码,则数据通过二进制的形式传送到服务器端,这时如果用request是无法直接获取到相应表单的值的,而应该通过stream流对象,将传到服务器端的二进制数据解码,从而读取数据。如果要上传文件的话,是一定要将encotype设置为multipart/form-data的。
所以,如果是在jsp中应这样来写文件上传的表单:
三、服务端fileupload接收文件
1. 使用 fileupload 解析request
[java]
view plain
copy
print?
DiskFileItemFactory dff = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(dff);
List<FileItem> items = sfu.parseRequest(request);
DiskFileItemFactory dff = new DiskFileItemFactory(); ServletFileUpload sfu = new ServletFileUpload(dff); List<FileItem> items = sfu.parseRequest(request);
断点调试图如下:
通过断点调试图,可以看到上传文件封装到FileItem的属性,我们最关心的是fieldName、fileName、以及临时文件tempFile。
2. 获取上传字段
由于只包含一个上传文件的字段,所以可以通过以下获取上传字段:[java]
view plain
copy
print?
// 获取上传字段
FileItem fileItem = items.get(0);
// 获取上传字段 FileItem fileItem = items.get(0);
3. 更改文件名称为唯一
由于多次上传的文件名称可能相同,为了避免上传的文件被覆盖,需要将上传的文件名做唯一处理:[java]
view plain
copy
print?
// 更改文件名为唯一的
String filename = fileItem.getName();
if (filename != null) {
filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
}
// 更改文件名为唯一的 String filename = fileItem.getName(); if (filename != null) { filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename); }这里的generateGUID()来产生随机的32位16进置值:
[java]
view plain
copy
print?
/**
* 生成UUID
*
* @return UUID
*/
public static String generateGUID() {
return new BigInteger(165, new Random()).toString(36).toUpperCase();
}
/** * 生成UUID * * @return UUID */ public static String generateGUID() { return new BigInteger(165, new Random()).toString(36).toUpperCase(); }
4. 生成存储路径
我们可以通过[java]
view plain
copy
print?
String storeDirectory = getServletContext().getRealPath("/files/images");
String storeDirectory = getServletContext().getRealPath("/files/images");
来获取项目下的files/images文件夹,但是如果上传的文件非常多时以后检索该文件夹就比较费时,这里通过文件的哈希来进行二级目录划分,每个目录16个文件夹,这样最多划分出256个文件夹。
[java]
view plain
copy
print?
// 计算文件的存放目录
private String genericPath(String filename, String storeDirectory) {
int hashCode = filename.hashCode();
int dir1 = hashCode&0xf;
int dir2 = (hashCode&0xf0)>>4;
String dir = "/"+dir1+"/"+dir2;
File file = new File(storeDirectory,dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
// 计算文件的存放目录 private String genericPath(String filename, String storeDirectory) { int hashCode = filename.hashCode(); int dir1 = hashCode&0xf; int dir2 = (hashCode&0xf0)>>4; String dir = "/"+dir1+"/"+dir2; File file = new File(storeDirectory,dir); if(!file.exists()){ file.mkdirs(); } return dir; }
5. 存储文件
[java]view plain
copy
print?
fileItem.write(new File(storeDirectory + path, filename));
String filePath = "/files/images" + path + "/" + filename;
fileItem.write(new File(storeDirectory + path, filename)); String filePath = "/files/images" + path + "/" + filename;
6. 响应文件存储地址
[java]view plain
copy
print?
String filePath = "/files/images" + path + "/" + filename;
response.getWriter().write(filePath);
String filePath = "/files/images" + path + "/" + filename; response.getWriter().write(filePath);
通过以上步骤,就将上传的文件存储到了服务器,并将文件的存储相对项目地址返回。
四、客户端OkHttp上传文件
1、监听裁剪结果
在上一篇《Android
拍照、选择图片并裁剪》中,我们通过设置裁剪图片的监听获取到裁剪后的图片:
[java]
view plain
copy
print?
// 设置裁剪图片结果监听
setOnPictureSelectedListener(new OnPictureSelectedListener() {
@Override
public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
mPictureIv.setImageBitmap(bitmap);
String filePath = fileUri.getEncodedPath();
String imagePath = Uri.decode(filePath);
Toast.makeText(mContext, "图片已经保存到:" + imagePath, Toast.LENGTH_LONG).show();
}
});
// 设置裁剪图片结果监听 setOnPictureSelectedListener(new OnPictureSelectedListener() { @Override public void onPictureSelected(Uri fileUri, Bitmap bitmap) { mPictureIv.setImageBitmap(bitmap); String filePath = fileUri.getEncodedPath(); String imagePath = Uri.decode(filePath); Toast.makeText(mContext, "图片已经保存到:" + imagePath, Toast.LENGTH_LONG).show(); } });
2. 使用OkHttp上传图片文件
我们将裁剪图片结果的监听回调修改如下,即裁剪完成后就上传图片到服务器
[java]
view plain
copy
print?
// 设置裁剪图片结果监听
setOnPictureSelectedListener(new OnPictureSelectedListener() {
@Override
public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
// mPictureIv.setImageBitmap(bitmap);
String filePath = fileUri.getEncodedPath();
final String imagePath = Uri.decode(filePath);
uploadImage(imagePath);
}
});
// 设置裁剪图片结果监听 setOnPictureSelectedListener(new OnPictureSelectedListener() { @Override public void onPictureSelected(Uri fileUri, Bitmap bitmap) { // mPictureIv.setImageBitmap(bitmap); String filePath = fileUri.getEncodedPath(); final String imagePath = Uri.decode(filePath); uploadImage(imagePath); } });
3. 上传图片Task编写
由于OkHttp虽然有异步网络访问,但是回调还是处在子线程不能修改界面,这里编写一个NetworkTask来进行子线程到主线程的链接。
[java]
view plain
copy
print?
/**
* 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
*/
class NetworkTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return doPost(params[0]);
}
@Override
protected void onPostExecute(String result) {
Log.i(TAG, "服务器响应" + result);
}
}
/** * 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果 */ class NetworkTask extends AsyncTask<String, Integer, String> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... params) { return doPost(params[0]); } @Override protected void onPostExecute(String result) { Log.i(TAG, "服务器响应" + result); } }
4. OkHttp上传文件编写
在NetworkTask中,我们可以看到OkHttp上传的时候只有给它一个要上传文件的路径就可以了,然后返回上传后服务器返回的路径。
OkHttp提供了MultipartBody来进行文件的上传:
[java]
view plain
copy
print?
private String doPost(String imagePath) {
OkHttpClient mOkHttpClient = new OkHttpClient();
String result = "error";
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.addFormDataPart("image", imagePath,
RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
RequestBody requestBody = builder.build();
Request.Builder reqBuilder = new Request.Builder();
Request request = reqBuilder
.url(Constant.BASE_URL + "/uploadimage")
.post(requestBody)
.build();
Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
try{
Response response = mOkHttpClient.newCall(request).execute();
Log.d(TAG, "响应码 " + response.code());
if (response.isSuccessful()) {
String resultValue = response.body().string();
Log.d(TAG, "响应体 " + resultValue);
return resultValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private String doPost(String imagePath) { OkHttpClient mOkHttpClient = new OkHttpClient(); String result = "error"; MultipartBody.Builder builder = new MultipartBody.Builder(); builder.addFormDataPart("image", imagePath, RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath))); RequestBody requestBody = builder.build(); Request.Builder reqBuilder = new Request.Builder(); Request request = reqBuilder .url(Constant.BASE_URL + "/uploadimage") .post(requestBody) .build(); Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage"); try{ Response response = mOkHttpClient.newCall(request).execute(); Log.d(TAG, "响应码 " + response.code()); if (response.isSuccessful()) { String resultValue = response.body().string(); Log.d(TAG, "响应体 " + resultValue); return resultValue; } } catch (Exception e) { e.printStackTrace(); } return result; }
5. 通过Glide加载图片
[java]view plain
copy
print?
/**
* 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
*/
class NetworkTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return doPost(params[0]);
}
@Override
protected void onPostExecute(String result) {
if(!"error".equals(result)) {
Log.i(TAG, "图片地址 " + Constant.BASE_URL + result);
Glide.with(mContext)
.load(Constant.BASE_URL + result)
.into(mPictureIv);
}
}
}
/** * 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果 */ class NetworkTask extends AsyncTask<String, Integer, String> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... params) { return doPost(params[0]); } @Override protected void onPostExecute(String result) { if(!"error".equals(result)) { Log.i(TAG, "图片地址 " + Constant.BASE_URL + result); Glide.with(mContext) .load(Constant.BASE_URL + result) .into(mPictureIv); } } }
OK,图片加载出来了,来看下我们设置的Log日志:
五、客户端上传用户ID及图片
以下作为一个demo,演示客户端上传图片的时候并携带用户的ID,这样传递到服务器之后就可以根据用户的ID去修改用户头像了,服务器端一般是处理用户数据库的业务,这里只是简单的打印处理。1. 客户端添加参数
客户端只需要添加一个用户Id的字段就可以了
[java]
view plain
copy
print?
// 这里演示添加用户ID
builder.addFormDataPart("userId", "20160519142605");
// 这里演示添加用户ID builder.addFormDataPart("userId", "20160519142605");
整体代码如下:
[java]
view plain
copy
print?
private String doPost(String imagePath) {
OkHttpClient mOkHttpClient = new OkHttpClient();
String result = "error";
MultipartBody.Builder builder = new MultipartBody.Builder();
// 这里演示添加用户ID
builder.addFormDataPart("userId", "20160519142605");
builder.addFormDataPart("image", imagePath,
RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
RequestBody requestBody = builder.build();
Request.Builder reqBuilder = new Request.Builder();
Request request = reqBuilder
.url(Constant.BASE_URL + "/uploadimage")
.post(requestBody)
.build();
Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
try{
Response response = mOkHttpClient.newCall(request).execute();
Log.d(TAG, "响应码 " + response.code());
if (response.isSuccessful()) {
String resultValue = response.body().string();
Log.d(TAG, "响应体 " + resultValue);
return resultValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private String doPost(String imagePath) {
OkHttpClient mOkHttpClient = new OkHttpClient();
String result = "error";
MultipartBody.Builder builder = new MultipartBody.Builder();
// 这里演示添加用户ID builder.addFormDataPart("userId", "20160519142605");
builder.addFormDataPart("image", imagePath,
RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
RequestBody requestBody = builder.build();
Request.Builder reqBuilder = new Request.Builder();
Request request = reqBuilder
.url(Constant.BASE_URL + "/uploadimage")
.post(requestBody)
.build();
Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
try{
Response response = mOkHttpClient.newCall(request).execute();
Log.d(TAG, "响应码 " + response.code());
if (response.isSuccessful()) {
String resultValue = response.body().string();
Log.d(TAG, "响应体 " + resultValue);
return resultValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
2. 服务器端接收
[java]view plain
copy
print?
// 修改用户的图片
private void changeUserImage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String message = "";
try{
DiskFileItemFactory dff = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(dff);
List<FileItem> items = sfu.parseRequest(request);
for(FileItem item:items){
if(item.isFormField()){
//普通表单
String fieldName = item.getFieldName();
String fieldValue = item.getString();
System.out.println("name="+fieldName + ", value="+ fieldValue);
} else {// 获取上传字段
// 更改文件名为唯一的
String filename = item.getName();
if (filename != null) {
filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
}
// 生成存储路径
String storeDirectory = getServletContext().getRealPath("/files/images");
File file = new File(storeDirectory);
if (!file.exists()) {
file.mkdir();
}
String path = genericPath(filename, storeDirectory);
// 处理文件的上传
try {
item.write(new File(storeDirectory + path, filename));
String filePath = "/files/images" + path + "/" + filename;
System.out.println("filePath="+filePath);
message = filePath;
} catch (Exception e) {
message = "上传图片失败";
}
}
}
} catch (Exception e) {
e.printStackTrace();
message = "上传图片失败";
} finally {
response.getWriter().write(message);
}
}
// 修改用户的图片
private void changeUserImage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String message = "";
try{
DiskFileItemFactory dff = new DiskFileItemFactory(); ServletFileUpload sfu = new ServletFileUpload(dff); List<FileItem> items = sfu.parseRequest(request);
for(FileItem item:items){
if(item.isFormField()){
//普通表单
String fieldName = item.getFieldName();
String fieldValue = item.getString();
System.out.println("name="+fieldName + ", value="+ fieldValue);
} else {// 获取上传字段
// 更改文件名为唯一的
String filename = item.getName();
if (filename != null) {
filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
}
// 生成存储路径
String storeDirectory = getServletContext().getRealPath("/files/images");
File file = new File(storeDirectory);
if (!file.exists()) {
file.mkdir();
}
String path = genericPath(filename, storeDirectory);
// 处理文件的上传
try {
item.write(new File(storeDirectory + path, filename));
String filePath = "/files/images" + path + "/" + filename;
System.out.println("filePath="+filePath);
message = filePath;
} catch (Exception e) {
message = "上传图片失败";
}
}
}
} catch (Exception e) {
e.printStackTrace();
message = "上传图片失败";
} finally {
response.getWriter().write(message);
}
}
当然这里只是演示如何接收用户ID以及图片,具体的业务要具体实现。控制台打印结果如下:
六、源码及示例
ImageUpload Android端 + 服务器端代码七、测试提示
在自己测试的时候,可以选用本地的tomcat,然后电脑和手机在同一网段内就可以了(连接同一个wifi),ip地址查看方法:八、结语
通过上一篇博客《Android
拍照、选择图片并裁剪》以及该篇《Android 上传图片到JavaWeb服务器》,相信朋友们对于裁剪图片并上传服务器有了大致的了解,当然实现方式只是一种,主要是理清思路并灵活运用。
相关文章推荐
- Android 上传图片到JavaWeb服务器
- Android上传图片到服务器
- android通过Base64往服务器上传图片和对象
- Android: 上传图片到服务器
- android上传手机图片至服务器,服务器进行保存
- android选择图片或拍照图片上传到服务器(包括上传参数)
- android上传图片到服务器中的功能
- android上传图片至服务器
- android上传图片至服务器
- android选择图片或拍照图片上传到服务器(包括上传参数)
- android上传图片并附带参数至服务器
- android上传图片至服务器
- android从本地媒体库获取图片上传至服务器保存
- android上传图片至服务器
- Android上传图片至服务器
- android通过Base64往服务器上传图片和对象
- 上传android手机图片到服务器的方法
- android上传图片和参数(属性)到服务器
- Android 上传图片到服务器
- Android拍照选择图片通过webservice上传图片到到服务器