android开发服务器程序,Android程序开发通过HttpURLConnection上传文件到服务器

一:实现原理

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

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

服务器端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;

}

Android客户端基于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开发再也不需要它了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值