1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.tradefed.util.net; 17 18 import com.android.tradefed.util.StreamUtil; 19 import com.android.tradefed.util.net.IHttpHelper.DataSizeException; 20 21 import java.io.File; 22 import java.io.FileInputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 26 /** 27 * Helper class for making multipart HTTP post requests. This class is used to upload files 28 * using multipart HTTP post (RFC 2388). 29 * 30 * To send multipart posts create this object passing it the url to send the requests to. 31 * Then set necessary parameters using the addParameter method and specify a file to upload 32 * using addFile method. After everything is set, send the request using the send method. 33 * 34 * Currently the implementation only supports 'text/plain' content types. 35 */ 36 public class HttpMultipartPost { 37 38 private static final String CONTENT_TYPE = "text/plain"; 39 private static final String BOUNDARY = "xXxXx"; 40 private static final String HYPHENS = "--"; 41 private static final String CRLF = "\r\n"; 42 43 private StringBuilder mBuilder; 44 private String mUrl; 45 private IHttpHelper mHelper; 46 47 public HttpMultipartPost(String url, IHttpHelper httpHelper) { 48 mBuilder = new StringBuilder(); 49 mUrl = url; 50 mHelper = httpHelper; 51 } 52 53 public HttpMultipartPost(String url) { 54 this(url, new HttpHelper()); 55 } 56 57 /** 58 * Adds a string parameter to the request. 59 * @param name name of the parameter. 60 * @param value value of the parameter. 61 * @throws IOException 62 */ 63 public void addParameter(String name, String value) throws IOException { 64 mBuilder.append(HYPHENS + BOUNDARY + CRLF); 65 mBuilder.append(String.format( 66 "Content-Disposition: form-data; name=\"%s\"%s%s", name, CRLF, 67 CRLF)); 68 mBuilder.append(value); 69 mBuilder.append(CRLF); 70 } 71 72 /** 73 * Add a file parameter to the request. Opens the file, reads its contents 74 * and sends them as part of the request. Currently the implementation 75 * only supports 'text/plain' content type. 76 * @param name name of the parameter. 77 * @param file file whose contents will be uploaded as part of the request. 78 * @throws IOException 79 */ 80 public void addTextFile(String name, File file) throws IOException { 81 FileInputStream in = new FileInputStream(file); 82 String fileName = file.getAbsolutePath(); 83 84 addTextFile(name, fileName, in); 85 86 in.close(); 87 } 88 89 /** 90 * Add a file parameter to the request. The contents of the file to upload 91 * will come from reading the input stream. Currently the implementation only 92 * supports 'text/plain' content type. 93 * @param name name of the parameter. 94 * @param fileName file name to report for the data in the stream. 95 * @param in stream whose contents are being uploaded. 96 * @throws IOException 97 */ 98 public void addTextFile(String name, String fileName, InputStream in) 99 throws IOException { 100 101 mBuilder.append(HYPHENS + BOUNDARY + CRLF); 102 mBuilder.append(String.format( 103 "Content-Disposition: form-data; name=\"%s\";filename=\"%s\"%s", 104 name, fileName, CRLF)); 105 mBuilder.append(String.format("Content-Type: %s%s", CONTENT_TYPE, CRLF)); 106 mBuilder.append(CRLF); 107 108 mBuilder.append(StreamUtil.getStringFromStream(in)); 109 110 mBuilder.append(CRLF); 111 } 112 113 /** 114 * Sends the request to the server. 115 * @throws IOException 116 * @throws DataSizeException 117 */ 118 public void send() throws IOException, DataSizeException { 119 mBuilder.append(HYPHENS + BOUNDARY + HYPHENS); 120 mBuilder.append(CRLF + CRLF); 121 mHelper.doPostWithRetry(mUrl, mBuilder.toString(), 122 "multipart/form-data;boundary=" + BOUNDARY); 123 } 124 } 125