Android开发上传图片到后台服务器并获取
首先,使用okhttp与后台建立连接,代码如下:
public class OkmyHttp {
public interface OnHttpResult//定义一个封装接口,没有什么意义,如果需要则在实现的类里面进行具体定义
{
void OnResult(JSONObject jsonObject);
}
OnHttpResult myResultListener;//相当于一个监听器
Context context;
public OkmyHttp(Context context, OnHttpResult ResultListener)
{
this.context= (Context) context;
this.myResultListener= (OnHttpResult) ResultListener;
}
Handler handler=new Handler()
{
@Override
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
String string=(String)msg.obj;
if (string.equals("")) {
Toast.makeText(context, "服务器数据为空", Toast.LENGTH_LONG).show();
}
else
{
try {
JSONObject jsonObject=new JSONObject(string);
myResultListener.OnResult(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(context,
"不是JSON对象"+ string,Toast.LENGTH_LONG).show();
}
}
break;
case 1:
Toast.makeText(context,
"访问网络信息出错"+(String)msg.obj,Toast.LENGTH_LONG).show();
break;
}
}
};
String url = "存放需要连接的后台地址";
OkHttpClient client = new OkHttpClient(); //创建okHttpClient对象
//该程序下载URL并将其内容打印为字符串。
public boolean Send(final String date,String URL) {
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
,date);
//MediaType指的是要传递的数据的MIME类型,MediaType对象包含了三种信息:type 、subtype以及charset,
// 一般将这些信息传入parse()方法中,这样就可以解析出MediaType对象,类型:
// json : application/json
//xml : application/xml
//png : image/png
//jpg : image/jpeg
//gif : imge/gif
//post和get的不同在于对Request请求的构造不同(因为post需要携带参数),
// post方式中的Request需要传递一个RequestBody作为post的参数。RequestBody有两个子类:FormBody和MultipartBody;
//FromBody用于提交表单键值对,
Request request = new Request.Builder()//通过request的对象去构造得到一个Call对象,
.url(url+URL)// 类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
.post(requestBody)//默认是get请求,可以不写
.build();
Call call = client.newCall(request);//以异步的方式去执行请求,调用的是call.enqueue,将call加入调度队列,
// 然后等待任务执行完成,我们在Callback中即可得到结果。
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {//请求失败执行的方法
Message message = new Message();
message.what = 1;//表示标识的消息类型,当what=1表示网络访问错误
message.obj = e.getMessage();//表示收到的数据,放具体内容
handler.sendMessage(message);//发送消息到主线程
}
@Override
public void onResponse(Call call, Response response) throws IOException {//请求成功执行的方法,response就是从服务器得到的参
Message message = new Message();
message.what = 0;//表示标识的消息类型
message.obj =response.body().string(); //同步方式下得到返回结果,表示收到的数据,放具体内容
Log.i("网上返回的数据", String.valueOf(message.obj));
handler.sendMessage(message);
}
});
return true;
}
}
上传图片到后台:代码如下:
//将上面的定义的接口在这调用
OkmyHttp client = new OkmyHttp(this, myHttpListener);
//获取image中的缓存图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.margin_picture);
//把图片转换字节流
String images = compressImage(bitmap);
//将需要发送的数据存放在JSONObject中
JSONObject jsonObject = new JSONObject();
try {
//此处的变量名需要和后台的变量名相同
jsonObject.put("picturename", images);
client.Send(jsonObject.toString(), "LoginServlet");
} catch (JSONException e) {
e.printStackTrace();
}
此处为调用成功后后台的返回结果
OkmyHttp.OnHttpResult myHttpListener = new OkmyHttp.OnHttpResult() {
@Override
public void OnResult(JSONObject jsonObject) {
try {
if (jsonObject.getInt("code") == 200) {
Toast.makeText(LoginActivity.this, jsonObject.getString("message"), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, jsonObject.getString("message"), Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
//上面用的图片转换方法
//把图片转换成字节
@RequiresApi(api = Build.VERSION_CODES.O)
private static String compressImage(Bitmap bitmap) {
String result = null;
ByteArrayOutputStream baos=null;
try {
//1. 将BITMAP转成jpeg二进制数据
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
baos.close();
baos.flush();
byte[] bitmapBytes=baos.toByteArray();
bitmapBytes=GZipCompress(bitmapBytes);
//3. 将压缩后的字节流文件转成字符串
result = Base64.encodeToString(bitmapBytes,Base64.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (baos != null) {
baos.flush();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
//GZIP压缩
public static byte[] GZipCompress(byte[] data) {
if (data == null || data.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip;
try {
gzip = new GZIPOutputStream(out);
gzip.write(data);
gzip.close();
} catch ( Exception e) {
e.printStackTrace();
}
return out.toByteArray();
}
//GZIP解压
public static byte[] GZipUncompress(byte[] data) {
if (data == null || data.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(data);
try {
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
} catch (Exception e) {
e.printStackTrace();
}
return out.toByteArray();
}
获取后台返回的图片并进行处理:
//将上面的定义的接口在这调用
OkmyHttp client = new OkmyHttp(getActivity(), myHttpListener);
将需要获取图片的条件保存在JSONObject中发送到后台
JSONObject jsonObject=new JSONObject();
jsonObject.put("phone",GlobalObj.phone);
login.setVisibility(View.GONE);
client.Send(jsonObject.toString(),"SelectAllServlet");
private final static String URL_PATH = "图片存放地址";
//后台根据条件返回的结果在这里处理
OkmyHttp.OnHttpResult myHttpListener = new OkmyHttp.OnHttpResult() {
@Override
public void OnResult(JSONObject jsonObject) {
try {
//根据变量名得到后台返回的图片
String picturenameAll = jsonObject.getString("picturename");
String pictureURL = URL_PATH + "/" + picturenameAll;
//开启一个线程
Thread thread = new Thread() {
@Override
public void run() {
try {
//2:把网址封装为一个URL对象
URL url = new URL(pictureURL);
//3:获取客户端和服务器的连接对象,此时还没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4:初始化连接对象
conn.setRequestMethod("GET");
//设置连接超时
conn.setConnectTimeout(5000);
//设置读取超时
conn.setReadTimeout(5000);
//5:发生请求,与服务器建立连接
conn.connect();
//如果响应码为200,说明请求成功
if (conn.getResponseCode() == 200) {
//获取服务器响应头中的流
InputStream is = conn.getInputStream();
//读取流里的数据,构建成bitmap位图
Bitmap bitmap = BitmapFactory.decodeStream(is);
Log.d("获取的头像数据", String.valueOf(bitmap));
bitmap1 = bitmap;
//发生更新UI的消息
Message msg = handler.obtainMessage();
msg.obj = bitmap;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
//启动线程任务
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
} ;
//接收数据
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//更新UI
imageView.setImageBitmap((Bitmap) msg.obj);
userName.setText(usernameAll);
}
};
后台关于图片的处理:
//得到图片存放的真实路径
private String WEBROOT_URL=getServletContext().getRealPath("/image/");
//将手机端上传的图片进行处理
Map<String, Object> map = new HashMap<>();
try {
BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null) {
responseStrBuilder.append(inputStr);
}
System.out.println("recRegister:"+responseStrBuilder.toString());
JSONObject jsonObject = JSONObject.parseObject(responseStrBuilder.toString());
for (Object key : jsonObject.keySet()) {
map.put(key.toString(), jsonObject.get(key));
}
} catch (Exception e) {
e.printStackTrace();
}
//此处的变量名需要和手机端上传时的变量名相同
String picturename=ProcessPicField(map.get("picturename").toString());
//上面处理所需的方法
//对图片字段进行处理,并返回文件名
protected String ProcessPicField(String picdata){
byte[] bytes = Base64BitmapUtil.Base64ToBytes(picdata);
Date date = new Date();
String filename = date.getTime() +".jpg";
File file = new File(WEBROOT_URL);
if (!file.exists()){
file.mkdirs();
}
try {
String path = file.getAbsolutePath()+"/"+filename;
System.out.println("write file :"+path);
File file2 = new File(path);
FileOutputStream fos = new FileOutputStream(file2);
fos.write(bytes);
fos.flush();
fos.close();
return filename;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
上面所用到的一个工具类
/**
* Function:Base64和Bitmap相互转换类,转换之前,进行gzip压缩
*/
public class Base64BitmapUtil {
public static byte[] Base64ToBytes(String base64Data) {
byte[] bytes = Base64.getMimeDecoder().decode(base64Data);
return GZipUncompress(bytes);
}
//GZIP压缩
public static byte[] GZipCompress(byte[] data) {
if (data == null || data.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip;
try {
gzip = new GZIPOutputStream(out);
gzip.write(data);
gzip.close();
} catch (Exception e) {
e.printStackTrace();
}
return out.toByteArray();
}
//GZIP解压
public static byte[] GZipUncompress(byte[] data) {
if (data == null || data.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(data);
try {
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
} catch (Exception e) {
e.printStackTrace();
}
return out.toByteArray();
}
}
后台将所需信息输出是以JSON的方式,我使用的是将输出信息保存在javaBean中,然后转换成JSON对象,代码如下:
Gson gson = new Gson();
String json = gson.toJson(msgBean);
response.getWriter().write(json);