android开发之HttpUrlConnection与OkHttp实现文件上传下载
来源:互联网 发布:日本mma 知乎 编辑:程序博客网 时间:2024/06/11 16:41
首先来一点题外话:
Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient。
尽管Google在大部分安卓版本中推荐使用HttpURLConnection,但是这个类相比HttpClient实在是太难用,太弱爆了。
OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。
OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。
HttpClient地址:https://github.com/square/okhttp
第一:了解一下文件上传的原理
文件上传是我们项目中经常使用的功能,一般我们的服务器可能都是web服务器,当我们使用非浏览器客户端上传文件时,比如手机(Android)等上传,可能就需要对传输的数据进行规范化的拼接,说白了,就是我们得自己完成浏览器帮我们做的事。
我首先写了服务器端代码,用来接收我们的数据,一会会贴出源码。然后写了个web页面用于上次,便于我们看其中的原理。
当点击了上传以后,这里我使用了firefox的firebug来观察网络信息,可以看到发出了一个POST请求,下面我框出的是请求头信息。里面包含一些请求的配置数据。
接下来看这张图:
我们可以看到我们发送的数据,一个是name为username的普通表单数据,一个为name为uploadFile的一个文件数据,可以看得出来,浏览器把文件数据转化成了2进制然后按特定的格式发给服务器了。
1、使用HttpUrlConnection/** * * @param params * 传递的普通参数 * @param uploadFile * 需要上传的文件名 * @param fileFormName * 需要上传文件表单中的名字 * @param newFileName * 上传的文件名称,不填写将为uploadFile的名称 * @param urlStr * 上传的服务器的路径 * @throws IOException */ public static void uploadForm(Map<String, String> params, String fileFormName, File uploadFile, String newFileName, String urlStr) throws IOException { if (newFileName == null || newFileName.trim().equals("")) { newFileName = uploadFile.getName(); } StringBuilder sb = new StringBuilder(); /** * 普通的表单数据 */ if (params != null) for (String key : params.keySet()) { sb.append("--" + BOUNDARY + "\r\n"); sb.append("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n"); sb.append("\r\n"); sb.append(params.get(key) + "\r\n"); } /** * 上传文件的头 */ sb.append("--" + BOUNDARY + "\r\n"); sb.append("Content-Disposition: form-data; name=\"" + fileFormName + "\"; filename=\"" + newFileName + "\"" + "\r\n"); sb.append("Content-Type: image/jpeg" + "\r\n");// 如果服务器端有文件类型的校验,必须明确指定ContentType sb.append("\r\n"); byte[] headerInfo = sb.toString().getBytes("UTF-8"); byte[] endInfo = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("UTF-8"); System.out.println(sb.toString()); URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); conn.setRequestProperty("Content-Length", String .valueOf(headerInfo.length + uploadFile.length() + endInfo.length)); conn.setDoOutput(true); OutputStream out = conn.getOutputStream(); InputStream in = new FileInputStream(uploadFile); out.write(headerInfo); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) out.write(buf, 0, len); out.write(endInfo); in.close(); out.close(); if (conn.getResponseCode() == 200) { System.out.println("上传成功"); } }使用HttpUrlConnection上传有一个很致命的问题就是,当上传文件很大时,会发生内存溢出,手机分配给我们app的内存更小,所以就更需要解决这个问题。
2. 使用okHttp框架来上传文件
public static void testUploadFile(String url) { //创建OkHttpClient对象 OkHttpClient mOkHttpClient = new OkHttpClient(); File file = new File(Environment.getExternalStorageDirectory(), "下载中的压缩包.zip"); //application/octet-stream 表示类型是二进制流,不知文件具体类型 RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); RequestBody requestBody = new MultipartBuilder() .type(MultipartBuilder.FORM) .addPart(Headers.of( "Content-Disposition", "form-data; name=\"username\""), RequestBody.create(null, "***")) .addPart(Headers.of( "Content-Disposition", "form-data; name=\"mFile\";filename=\"下载中的压缩包.zip\""), fileBody) .build(); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(Response response) throws IOException { System.out.println(response.body().string()); } }); }
3. 文件下载,就是拿到inputStream做写文件操作。
3.1 HttpURLConnection的方式:
public static void downloadFile(String fileName) throws IOException {String uploadUrl = "http://192.168.2.111:8080/HsbServlet/DownloadFile";File file = new File(fileName + "/dog.jpg");OutputStream os = new BufferedOutputStream(new FileOutputStream(file));final URL url = new URL(uploadUrl);HttpURLConnection connection = (HttpURLConnection) url.openConnection();InputStream is = new BufferedInputStream(connection.getInputStream());int len = 0;byte[] buffer = new byte[1024];while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);// 必须使用write(buffer, 0, len){Writes}os.flush();os.close();is.close();connection.disconnect();}3.2 OkHttp方式:
public static void downloadAsyn(final String url, final String destFileDir) { OkHttpClient mOkHttpClient = new OkHttpClient(); final Request request = new Request.Builder() .url(url) .build(); final Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(final Request request, final IOException e) { } @Override public void onResponse(Response response) { System.out.println(response.isSuccessful()); InputStream is = null; byte[] buf = new byte[2048]; int len = 0; FileOutputStream fos = null; try { is = response.body().byteStream(); File file = new File(Environment.getExternalStorageDirectory() + "/aa.zip"); fos = new FileOutputStream(file); while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); } fos.flush(); //如果下载文件成功,第一个参数为文件的绝对路径 } catch (IOException e) { } finally { try { if (is != null) is.close(); } catch (IOException e) { } try { if (fos != null) fos.close(); } catch (IOException e) { } } } }); }
参考文章:
http://blog.csdn.net/lmj623565791/article/details/47911083
http://blog.csdn.net/lmj623565791/article/details/23781773
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
- android开发之HttpUrlConnection与OkHttp实现文件上传下载
- Android--okhttp与php交互,文件上传下载
- Android okHttp网络请求之文件上传下载
- Android okHttp网络请求之文件上传下载
- Android okHttp网络请求之文件上传下载
- Android端通过Okhttp与PHP服务器进行交互并实现文件上传下载(一)
- Android端通过Okhttp与PHP服务器进行交互并实现文件上传下载(二)
- Android okHttp 实战(二):okHttp网络请求之文件上传下载
- iOS开发之实现文件上传下载
- Web开发之JspSmartUpload实现文件上传下载
- android网络访问之HttpURLConnection vs OkHttp
- okhttp 文件上传下载
- Android开发之HttpURLConnection
- Android安全开发之正确使用Https(内含OkHttp、HttpUrlConnection配置https方式)
- iOS开发之结合asp.net webservice实现文件上传下载
- iOS开发之结合asp.net webservice实现文件上传下载
- iOS开发之结合asp.net webservice实现文件上传下载
- iOS开发之结合asp.net webservice实现文件上传下载
- sendfile详解
- 修改 sparkmetadata,使thrift server支持中文
- C++之fstream
- angularjs 表单验证
- CreateProcess创建telnet进程提示文件不存在
- android开发之HttpUrlConnection与OkHttp实现文件上传下载
- mdadm命令详解
- Xcode多语言本地化
- Linux 设备驱动的固件加载
- JS的Math以及Date对象
- winform 窗体 键盘按键 获取
- 线程特定数据(TSD)
- java的IO流中,更改输入源与输出源
- 一个萝卜一个坑