OkHttp
OkHttp的项目主页地址是:https://github.com/square/okhttp
Overview
HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP efficiently makes your stuff load faster and saves bandwidth.
OkHttp is an HTTP client that’s efficient by default:
- HTTP/2 support allows all requests to the same host to share a socket.
- Connection pooling reduces request latency (if HTTP/2 isn’t available).
- Transparent GZIP shrinks download sizes.
- Response caching avoids the network completely for repeat requests.
OkHttp perseveres when the network is troublesome: it will silently recover from common connection problems. If your service has multiple IP addresses OkHttp will attempt alternate addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant data centers. OkHttp initiates new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.
Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.
OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.
OkHttp使用(需要上传图片和对应的参数信息)
1.首先需要添加OkHttp库的依赖。编辑app/build.gradle文件,在dependencies闭包中添加如下内容:
compile 'com.squareup.okhttp3:okhttp:(insert latest version)'
添加上述依赖后会自动下载两个库,一个是OkHttp库,一个是Okio库,后者是前者的通信基础。
2.Android客户端关键代码如下:
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))); //传递图片的同时上传照片对应的包裹信息 builder.addFormDataPart("baggage_no", "9999"); builder.addFormDataPart("flight_id", "99"); builder.addFormDataPart("record_status", "1"); builder.addFormDataPart("create_person", Utility.getStringFromMainSP(this, Comparams.SP_MAIN_USERNAME)); builder.addFormDataPart("update_person", Utility.getStringFromMainSP(this, Comparams.SP_MAIN_USERNAME)); RequestBody requestBody = builder.build(); Request.Builder reqBuilder = new Request.Builder(); Request request = reqBuilder .url(BASE_URL + "/uploadimage") .post(requestBody) .build(); Log.d(TAG, "请求地址 " + 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; }
3.服务器端关键代码如下:
package com.rgd.uploadserver; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; import javax.mail.internet.NewsAddress; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; /** * 违规拍照上传 */ public class UploadImageServlet extends HttpServlet { private String baggage_no;//行李编号 private int flight_id;//航班id private int record_status;//记录状态 private String create_person;//创建人 private String update_person;//更新人 @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * 防止乱码 */ response.setContentType("text/html;charset=utf-8"); response. setCharacterEncoding("UTF-8"); request. setCharacterEncoding("UTF-8"); System.out.println("Post请求成功"); /*baggage_no=request.getParameter("baggage_no"); String flight_idString=request.getParameter("flight_id"); flight_id=Integer.parseInt(flight_idString); record_status=Integer.parseInt(request.getParameter("record_status")); create_person=request.getParameter("create_person"); update_person=request.getParameter("update_person");*/ //接收图片 uploadImage(request, response); System.out.println("步骤6:uploadImage"); response.getWriter().append("Post请求成功"); } // 上传图片文件和相关字段 private void uploadImage(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); // 获取上传字段 FileItem fileItem = items.get(0); baggage_no = items.get(1).getString(); flight_id=Integer.parseInt(items.get(2).getString()); record_status = Integer.parseInt(items.get(3).getString()); create_person = items.get(4).getString(); update_person = items.get(5).getString(); System.out.println("item的数量:"+items.size()); System.out.println("baggage_no为:"+baggage_no); // 更改文件名为唯一的 String filename = fileItem.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); String path =getPath(storeDirectory); System.out.println("path为:"+path); // 处理文件的上传 try { fileItem.write(new File(storeDirectory + path, filename)); String filePath = "/files/images" +path + "/" + filename; message = filePath; System.out.println("jdbc.doGet()图片存储路径"+filePath); //上传成功才将数据信息写到数据库 insertDatabase(baggage_no,flight_id,filePath,record_status,create_person,update_person); } catch (Exception e) { message = "上传图片失败"; } } catch (Exception e) { message = "上传图片失败"; } finally { response.getWriter().write(message); } } private void insertDatabase(String baggage_no,int flight_id,String filePath, int record_status,String create_person, String update_person) { //通过JDBC将文件路径filePath写入到数据库,还要将飞机航班信息上传到服务器上 //先设置好编码 try { try { Class.forName("com.mysql.jdbc.Driver"); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Connection connection = DriverManager.getConnection("jdbc:mysql://10.2.135.191:3306/auto_sorting","root","root1234!"); //String insertString="insert into register (email,password)values(?,?)"; String insertString="insert into baggage_illegal_picture_info (baggage_no,flight_id,photo_path,record_status," + "" + " create_time,create_person,update_time,update_person) values(?,?,?,?,?,?,?,?)"; PreparedStatement ps = connection.prepareStatement(insertString); ps.setString(1, baggage_no);//包裹编号 ps.setInt(2, flight_id);//航班号 ps.setString(3, filePath);//照片路径 ps.setInt(4, record_status);//记录状态,如果上传成功则传1,失败传0 Timestamp timestamp = new Timestamp(new java.util.Date().getTime()); System.out.println(timestamp.toString()); ps.setTimestamp(5, timestamp);//创建时间 ps.setString(6, create_person);//记录创建人名字 ps.setTimestamp(7, timestamp);//记录更新时间 ps.setString(8, update_person);//记录更新人名字 ps.executeUpdate(); System.out.println("jdbc.doGet()+插入成功"); //关闭资源 ps.close(); connection.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //计算文件的存放目录 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 getPath(String storeDirectory) { String date=(new java.sql.Date(System.currentTimeMillis()).toString()); System.out.println("当前日期为:"+date); String dir="/"+date; File file = new File(storeDirectory, dir); if (!file.exists()) { file.mkdirs(); } return dir; } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
注:服务器端接受参数的request.getParameter取不到值,待研究。
服务器端代码请注意是否正确配置web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app 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"> <display-name></display-name> <servlet> <servlet-name>UploadImageServlet</servlet-name> <servlet-class>com.rgd.uploadserver.UploadImageServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadImageServlet</servlet-name> <url-pattern>/uploadimage</url-pattern> <url-pattern>/uploadkeyvalue</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>UploadKeyValueServlet</servlet-name> <servlet-class>com.rgd.uploadserver.UploadKeyValueServlet</servlet-class> </servlet> </web-app>
4.okHttp3下载文件相关代码(异步下载)
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(downloadUrl).build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.i(TAG,"OKhttp下载apk失败"); } @Override public void onResponse(Call call, Response response) throws IOException { InputStream is = response.body().byteStream(); FileOutputStream fos = new FileOutputStream(path); byte[] bytes=new byte[1024]; int lenth=-1; while ((lenth=is.read(bytes))!=-1){ fos.write(bytes,0,lenth); } fos.flush(); Log.i(TAG,"下载成功"); installApk(new File(path)); //用完将流关闭 is.close(); fos.close(); } });