Android端通過HttpURLConnection上傳檔案到server

來源:互聯網
上載者:User

標籤:ipa   代碼   上傳檔案   origin   upload   chunk   uuid   瀏覽器   java.net   

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 objectImageDto 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 DBimgUUID = 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; // defaultprivate 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 connectionURL url = new URL(requestURL.replace("{token}", this.token));urlConnection = (HttpURLConnection) url.openConnection();// create random boundaryRandom 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 formurlConnection.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 responseint 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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.