Android端通过HttpURLConnection上传文件到server

一:实现原理

近期在做Androidclient的应用开发,涉及到要把图片上传到后台server中。自己选择了做Spring3 MVC HTTP API作为后台上传接口,androidclient我选择用HttpURLConnection来通过form提交文件数据实现上传功能,本来想网上搜搜拷贝一下改改代码就好啦,发现根本没有现成的样例,多数的样例都是基于HttpClient的或者是基于Base64编码以后作为字符串来传输图像数据,于是我不得不自己动手。參考了网上一些资料,终于实现基于HttpURLConnection上传文件的androidclient代码,废话少说,事实上基于HttpURLConnection实现文件上传最关键的在于要熟悉Http协议相关知识。知道MIME文件块在Http协议中的格式表示,主要的数据传输格式例如以下:

当中boundary表示form的边界,仅仅要依照格式把内容字节数写到HttpURLConnection的对象输出流中,server端的Spring Controller 就会自己主动响应接受,跟从浏览器页面上上传文件是一样的。

server端HTTP API, 我是基于Spring3 MVC实现的Controller,代码例如以下:

@RequestMapping(value = "/uploadMyImage/{token}", method = RequestMethod.POST)
public @ResponseBody String getUploadFile(HttpServletRequest request, HttpServletResponse response,
@PathVariable String token) {
logger.info("spring3 MVC upload file with Multipart form");
logger.info("servlet context path : " + request.getSession().getServletContext().getRealPath("/"));
UserDto profileDto = userService.getUserByToken(token);
String imgUUID = "";
try {
if (request instanceof MultipartHttpServletRequest && profileDto.getToken() != null) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
logger.info("spring3 MVC upload file with Multipart form");
// does not work, oh my god!!
MultipartFile file = multipartRequest.getFiles("myfile").get(0);
InputStream input = file.getInputStream();
long fileSize = file.getSize();
BufferedImage image = ImageIO.read(input);
// create data transfer object
ImageDto dto = new ImageDto();
dto.setCreateDate(new Date());
dto.setFileName(file.getOriginalFilename());
dto.setImage(image);
dto.setCreator(profileDto.getUserName());
dto.setFileSize(fileSize);
dto.setType(ImageAttachmentType.CLIENT_TYPE.getTitle());
dto.setUuid(UUID.randomUUID().toString()); /// save to DB
imgUUID = imageService.createImage(dto);
input.close();
}
} catch (Exception e) {
e.printStackTrace();
logger.error("upload image error", e);
} return imgUUID;
}

Androidclient基于HttpURLConnection实现上传的代码,我把它封装成一个单独的类文件,这样大家能够直接使用,仅仅要传入上传的URL等參数就可以。代码例如以下:

package com.demo.http;

import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random; import android.os.Handler;
import android.util.Base64;
import android.util.Log; public class UploadImageTask implements APIURLConstants {
private String requestURL = DOMAIN_ADDRESS + UPLOAD_DESIGN_IMAGE_URL; // default
private final String CRLF = "\r\n";
private Handler handler;
private String token;
public UploadImageTask(String token, Handler handler) {
this.handler = handler;
this.token = token;
} public String execute(File...files) {
InputStream inputStream = null;
HttpURLConnection urlConnection = null;
FileInputStream fileInput = null;
DataOutputStream requestStream = null;
handler.sendEmptyMessage(50);
try {
// open connection
URL url = new URL(requestURL.replace("{token}", this.token));
urlConnection = (HttpURLConnection) url.openConnection();
// create random boundary
Random random = new Random();
byte[] randomBytes = new byte[16];
random.nextBytes(randomBytes);
String boundary = Base64.encodeToString(randomBytes, Base64.NO_WRAP); /* for POST request */
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestMethod("POST");
long size = (files[0].length() / 1024);
if(size >= 1000) {
handler.sendEmptyMessage(-150);
return "error";
}
// 构建Entity form
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
urlConnection.setRequestProperty("Cache-Control", "no-cache"); // never try to chunked mode, you need to set a lot of things
// if(size > 400) {
// urlConnection.setChunkedStreamingMode(0);
// }
// else {
// urlConnection.setFixedLengthStreamingMode((int)files[0].length());
// }
// end comment by zhigang on 2016-01-19 /* upload file stream */
fileInput = new FileInputStream(files[0]);
requestStream = new DataOutputStream(urlConnection.getOutputStream());
String nikeName = "myfile";
requestStream = new DataOutputStream(urlConnection.getOutputStream());
requestStream.writeBytes("--" + boundary + CRLF);
requestStream.writeBytes("Content-Disposition: form-data; name=\"" + nikeName + "\"; filename=\"" + files[0].getName() + "\""+ CRLF);
requestStream.writeBytes("Content-Type: " + getMIMEType(files[0]) + CRLF);
requestStream.writeBytes(CRLF);
// 写图像字节内容
int bytesRead;
byte[] buffer = new byte[8192];
handler.sendEmptyMessage(50);
while((bytesRead = fileInput.read(buffer)) != -1) {
requestStream.write(buffer, 0, bytesRead);
}
requestStream.flush();
requestStream.writeBytes(CRLF);
requestStream.flush();
requestStream.writeBytes("--" + boundary + "--" + CRLF);
requestStream.flush();
fileInput.close(); // try to get response
int statusCode = urlConnection.getResponseCode();
if (statusCode == 200) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
String imageuuId = HttpUtil.convertInputStreamToString(inputStream);
Log.i("image-uuid", "uploaded image uuid : " + imageuuId);
handler.sendEmptyMessage(50);
return imageuuId;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(requestStream != null) {
try {
requestStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileInput != null) {
try {
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConnection != null) {
urlConnection.disconnect();
}
}
handler.sendEmptyMessage(50);
return null;
} private String getMIMEType(File file) {
String fileName = file.getName();
if(fileName.endsWith("png") || fileName.endsWith("PNG")) {
return "image/png";
}
else {
return "image/jpg";
}
} }

经过本人測试,效果杠杠的!

所以请忘记HttpClient这个东西。android开发再也不须要它了。

Android端通过HttpURLConnection上传文件到server的更多相关文章

  1. Android端通过HttpURLConnection上传文件到服务器

    Android端通过HttpURLConnection上传文件到服务器 一:实现原理 最近在做Android客户端的应用开发,涉及到要把图片上传到后台服务器中,自己选择了做Spring3 MVC HT ...

  2. java http工具类和HttpUrlConnection上传文件分析

    利用java中的HttpUrlConnection上传文件,我们其实只要知道Http协议上传文件的标准格式.那么就可以用任何一门语言来模拟浏览器上传文件.下面有几篇文章从http协议入手介绍了java ...

  3. HttpURLConnection上传文件

    HttpURLConnection上传文件 import java.io.BufferedReader; import java.io.DataInputStream; import java.io. ...

  4. 工作笔记4.struts2上传文件到server

    本文介绍两种:上传文件到server的方式   一种是提交Form表单:还有一种是ajaxfileupload异步上传. 一.JSP中:     1.提交Form表单 为了能完毕文件上传,我们应该将这 ...

  5. android 使用AsyncHttpClient框架上传文件以及使用HttpURLConnection下载文件

    AsyncHttpClient开源框架android-async-http还是非常方便的. AsyncHttpClient该类通经常使用在android应用程序中创建异步GET, POST, PUT和 ...

  6. Java使用HttpURLConnection上传文件

    从普通Web页面上传文件非常easy.仅仅须要在form标签叫上enctype="multipart/form-data"就可以,剩余工作便都交给浏览器去完毕数据收集并发送Http ...

  7. Java使用HttpURLConnection上传文件(转)

    从普通Web页面上传文件很简单,只需要在form标签叫上enctype="multipart/form-data"即可,剩余工作便都交给浏览器去完成数据收集并发送Http请求.但是 ...

  8. Android用http协议上传文件

    http协议上传文件一般最大是2M,比较适合上传小于两M的文件   [代码] [Java]代码   001import java.io.File;  002import java.io.FileInp ...

  9. android 上传文件

    android对于上传文件,还是非常easy的,和java里面的上传都是一样的,基本上都是熟悉操作输出流和输入流!另一个特别重要的就是须要一些content-type这些參数的配置!  假设这些都弄好 ...

随机推荐

  1. BZOJ 4372/3370 烁烁的游戏/震波 (动态点分治+线段树)

    烁烁的游戏 题目大意: 给你一棵$n$个节点的树,有$m$次操作,询问某个节点的权值,或者将与某个点$x$距离不超过$d$的所有节点的权值都增加$w$ 动态点分裸题 每个节点开一棵权值线段树 对于修改 ...

  2. tomcat 映射虚拟路径

    编辑server.xml   在  <Host></Host>中添加 <Context path="/renbao/img/" docBase=&qu ...

  3. strlen()函数对一个未初始化数组的处理

    今天使用strlen时 ,发现一个问题,demo代码如下: #include <stdio.h> #include <stdlib.h> #include <string ...

  4. Eureka Server的REST端点

    Eureka Server的REST端点 Windows下面可以安装Curl: 使用more命令可以显示xml内容: D:\Java\IdeaProjects>more rest-api-tes ...

  5. Oracle性能分析1:开启SQL跟踪和获取trace文件

    当Oracle查询出现效率问题时,我们往往须要了解问题所在,这样才干针对问题给出解决方式.Oracle提供了SQL运行的trace信息,当中包括了SQL语句的文本信息.一些运行统计,处理过程中的等待, ...

  6. Unity学习笔记 之 发射小球碰撞物体的代码记录

    绑定在摄像机上的脚本 using UnityEngine; using System.Collections; public class abc : MonoBehaviour { //设置移动速度 ...

  7. CreateProcess

    #include <Windows.h> //WINBASEAPI //BOOL //WINAPI //CreateProcessW( //_In_opt_ LPCWSTR lpAppli ...

  8. ubuntu下创建文件夹快捷方式

    title: ubuntu下创建文件夹快捷方式 toc: false date: 2018-09-01 17:22:28 categories: methods tags: ubuntu 快捷方式 s ...

  9. 如何实现内核旁路(Kernel bypass)?

    转到 :http://blog.jobbole.com/94976/ 在前两篇文章中,我们讨论了<如何生成每秒百万级别的HTTP 请求?> 以及 如何减少往返时间 .我们在 Linux 上 ...

  10. HTML的常用标签属性及使用时需注意的一些细节

    前言 本篇随笔的主要是复习一下常用的一些HTML(Hyper Text Markup Language)标签及其属性,并总结一些使用过程中需要注意的一些细节,本篇提及的常用标签主要有: iframe标 ...