1 /* 2 * Copyright (C) 2011 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 17 package com.android.cts.tradefed.result; 18 19 import java.io.ByteArrayOutputStream; 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.io.OutputStream; 23 import java.io.OutputStreamWriter; 24 import java.io.PrintWriter; 25 import java.net.HttpURLConnection; 26 import java.net.URL; 27 import java.util.HashMap; 28 import java.util.Map; 29 30 /** MultipartForm builds a multipart form and submits it. */ 31 class MultipartForm { 32 33 private static final String FORM_DATA_BOUNDARY = "C75I55u3R3p0r73r"; 34 35 private final String mServerUrl; 36 37 private final Map<String, String> mFormValues = new HashMap<String, String>(); 38 39 private String mName; 40 private String mFileName; 41 private byte[] mData; 42 43 public MultipartForm(String serverUrl) { 44 mServerUrl = serverUrl; 45 } 46 47 public MultipartForm addFormValue(String name, String value) { 48 mFormValues.put(name, value); 49 return this; 50 } 51 52 public MultipartForm addFormFile(String name, String fileName, byte[] data) { 53 mName = name; 54 mFileName = fileName; 55 mData = data; 56 return this; 57 } 58 59 public void submit() throws IOException { 60 String redirectUrl = submitForm(mServerUrl); 61 if (redirectUrl != null) { 62 submitForm(redirectUrl); 63 } 64 } 65 66 /** 67 * @param serverUrl to post the data to 68 * @return a url if the server redirected to another url 69 * @throws IOException 70 */ 71 private String submitForm(String serverUrl) throws IOException { 72 HttpURLConnection connection = null; 73 try { 74 URL url = new URL(serverUrl); 75 connection = (HttpURLConnection) url.openConnection(); 76 connection.setInstanceFollowRedirects(false); 77 connection.setRequestMethod("POST"); 78 connection.setDoOutput(true); 79 connection.setRequestProperty("Content-Type", 80 "multipart/form-data; boundary=" + FORM_DATA_BOUNDARY); 81 82 byte[] body = getContentBody(); 83 connection.setRequestProperty("Content-Length", Integer.toString(body.length)); 84 85 OutputStream output = connection.getOutputStream(); 86 try { 87 output.write(body); 88 } finally { 89 output.close(); 90 } 91 92 // Open the stream to get a response. Otherwise request will be cancelled. 93 InputStream input = connection.getInputStream(); 94 input.close(); 95 96 if (connection.getResponseCode() == 302) { 97 return connection.getHeaderField("Location"); 98 } 99 } finally { 100 if (connection != null) { 101 connection.disconnect(); 102 } 103 } 104 105 return null; 106 } 107 108 private byte[] getContentBody() throws IOException { 109 ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); 110 PrintWriter writer = new PrintWriter(new OutputStreamWriter(byteOutput)); 111 writer.println(); 112 113 for (Map.Entry<String, String> formValue : mFormValues.entrySet()) { 114 writeFormField(writer, formValue.getKey(), formValue.getValue()); 115 } 116 117 if (mData != null) { 118 writeFormFileHeader(writer, mName, mFileName); 119 writer.flush(); // Must flush here before writing to the byte stream! 120 byteOutput.write(mData); 121 writer.println(); 122 } 123 writer.append("--").append(FORM_DATA_BOUNDARY).println("--"); 124 writer.flush(); 125 writer.close(); 126 return byteOutput.toByteArray(); 127 } 128 129 private void writeFormField(PrintWriter writer, String name, String value) { 130 writer.append("--").println(FORM_DATA_BOUNDARY); 131 writer.append("Content-Disposition: form-data; name=\"").append(name).println("\""); 132 writer.println(); 133 writer.println(value); 134 } 135 136 private void writeFormFileHeader(PrintWriter writer, String name, String fileName) { 137 writer.append("--").println(FORM_DATA_BOUNDARY); 138 writer.append("Content-Disposition: form-data; name=\"").append(name); 139 writer.append("\"; filename=\"").append(fileName).println("\""); 140 writer.println("Content-Type: application/x-gzip"); 141 writer.println("Content-Transfer-Encoding: binary"); 142 writer.println(); 143 } 144 } 145