標籤:
使用Http協議向伺服器傳遞圖片,那麼就要首先瞭解Http協議這個報文裡邊的資訊格式:
web端傳遞圖片一般都是使用表單的形式來傳遞的,通過post的形式傳遞的,在這裡要使用到兩個jar包,分別是:commons-fileupload.jar和commons-io.jar這倆jar包。
下邊來說一說Http協議上傳檔案標頭檔的格式:
其實我們這種前背景互動是用的HTTP協議。而http協議預設是傳的字串。所以我們上傳檔案的話要加enctype = "multipart/form-data"這個參數來說明我們這傳的是檔案不是字串了。而我們做web開發的時候,瀏覽器是自動解析HTTP協議的。裡面傳的哪些東西我們不用管。只要記住幾個參數就行。而我們要上傳的檔案報文是儲存在請求的標頭檔裡面的。下面就是上傳檔案標頭檔的格式:
POST/logsys/home/uploadIspeedLog!doDefault.html HTTP/1.1
Accept: text/plain, */*
Accept-Language: zh-cn
Host: 192.168.24.56
Content-Type:multipart/form-data;boundary=-----------------------------7db372eb000e2
User-Agent: WinHttpClient
Content-Length: 3693
Connection: Keep-Alive
-------------------------------7db372eb000e2
Content-Disposition: form-data; name="file"; filename="kn.jpg"
Content-Type: image/jpeg
(此處省略jpeg檔案位元據...)
-------------------------------7db372eb000e2--
這就是Http上傳發送的檔案格式。而我們要發送的時候必然要遵循這種格式來並且不能出一點差錯包括每行後面的斷行符號,下面一段文字是網上找的感覺寫的比較精彩。(尊重原創:http://topmanopensource.iteye.com/blog/1605238)
紅色字型部分就是協議的頭。給伺服器上傳資料時,並非協議頭每個欄位都得說明,其中,content-type是必須的,它包括一個類似標誌性質的名為boundary的標誌,它可以是隨便輸入的字串。對後面的具體內容也是必須的。它用來分辨一段內容的開始。Content-Length: 3693 ,這裡的3693是要上傳檔案的總長度。綠色字型部分就是需要上傳的資料,可以是文本,也可以是圖片等。資料內容前面需要有Content-Disposition, Content-Type以及Content-Transfer-Encoding等說明欄位。最後的紫色部分就是協議的結尾了。
注意這一行:
Content-Type: multipart/form-data; boundary=---------------------------7db372eb000e2
根據 rfc1867, multipart/form-data是必須的.
---------------------------7db372eb000e2 是分隔字元,分隔多個檔案、表單項。其中b372eb000e2 是即時產生的一個數字,用以確保整個分隔字元不會在檔案或表單項的內容中出現。Form每個部分用分隔字元分割,分隔字元之前必須加上"--"著兩個字元(即--{boundary})才能被http協議認為是Form的分隔字元,表示結束的話用在正確的分隔字元後面添加"--"表示結束。
前面的 ---------------------------7d 是 IE 特有的標誌,Mozila 為---------------------------71.
只要把這些Http協議的頭部的格式梳理清楚,然後再把圖片向伺服器傳遞:直接上代碼:
//用戶端代碼
public class HttpPost {/** * 通過拼接的方式構造請求內容,實現參數傳輸以及檔案傳輸 * * @param acti * .nUrl * @param params * @param files * @return * @throws IOException */public static String post(String actionUrl, Map<String, String> params, Map<String, File> files) throws IOException {String BOUNDARY = java.util.UUID.randomUUID().toString();String PREFIX = "--", LINEND = "\r\n";String MULTIPART_FROM_DATA = "multipart/form-data";String CHARSET = "UTF-8";URL uri = new URL(actionUrl);HttpURLConnection conn = (HttpURLConnection) uri.openConnection();conn.setReadTimeout(5 * 1000); // 緩衝的最長時間conn.setDoInput(true);// 允許輸入conn.setDoOutput(true);// 允許輸出conn.setUseCaches(false); // 不允許使用緩衝conn.setRequestMethod("POST");conn.setRequestProperty("connection", "keep-alive");conn.setRequestProperty("Charsert", "UTF-8");conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);// 首先組拼文本類型的參數StringBuilder sb = new StringBuilder();for (Map.Entry<String, String> entry : params.entrySet()) {sb.append(PREFIX);sb.append(BOUNDARY);sb.append(LINEND);sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);sb.append("Content-Transfer-Encoding: 8bit" + LINEND);sb.append(LINEND);sb.append(entry.getValue());sb.append(LINEND);}DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());outStream.write(sb.toString().getBytes());// 傳送檔案資料if (files != null)for (Map.Entry<String, File> file : files.entrySet()) {StringBuilder sb1 = new StringBuilder();sb1.append(PREFIX);sb1.append(BOUNDARY);sb1.append(LINEND);sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getKey() + "\"" + LINEND);sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);sb1.append(LINEND);outStream.write(sb1.toString().getBytes());InputStream is = new FileInputStream(file.getValue());byte[] buffer = new byte[1024];int len = 0;while ((len = is.read(buffer)) != -1) {outStream.write(buffer, 0, len);}is.close();outStream.write(LINEND.getBytes());}// 請求結束標誌byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();outStream.write(end_data);outStream.flush();// 得到響應碼int res = conn.getResponseCode();InputStream in = conn.getInputStream();if (res == 200) {int ch;StringBuilder sb2 = new StringBuilder();while ((ch = in.read()) != -1) {sb2.append((char) ch);}}outStream.close();conn.disconnect();return in.toString();}}
下邊是伺服器代碼:
public class UploadServlet extends HttpServlet {private static final long serialVersionUID = 1L;/** * Default constructor. */public UploadServlet() {// TODO Auto-generated constructor stub}/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stub}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {RequestContext req = new ServletRequestContext(request);if (FileUpload.isMultipartContent(req)) {DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);fileUpload.setFileSizeMax(1024 * 1024 * 1024);List items = new ArrayList();try {items = fileUpload.parseRequest(request);} catch (Exception e) {}Iterator it = items.iterator();while (it.hasNext()) {FileItem fileItem = (FileItem) it.next();if (fileItem.isFormField()) {System.out.println(fileItem.getFieldName()+ " "+ fileItem.getName()+ " "+ new String(fileItem.getString().getBytes("ISO-8859-1"), "GBK"));} else {System.out.println(fileItem.getFieldName() + " "+ fileItem.getName() + " " + fileItem.isInMemory()+ " " + fileItem.getContentType() + " "+ fileItem.getSize());if (fileItem.getName() != null && fileItem.getSize() != 0) {File fullFile = new File(fileItem.getName());File newFile = new File("F:\\upload\\"+ fullFile.getName());try {fileItem.write(newFile);} catch (Exception E) {}} else {System.out.println("no file choosen or empty file");}}}}}}
Android用戶端向伺服器傳遞圖片(使用Http協議)