package org.javalite.http; import org.javalite.common.Inflector; import java.io.*; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Sets up a Multipart request to send multiple text fields as well as upload files. * * @author Igor Polevoy on 5/1/16. */ public class Multipart extends Request<Multipart> { private static final String DASH = "------"; private static final String LINE_FEED = "\r\n"; private PrintWriter writer; private String boundary; private OutputStream outputStream; private List<FormField> formFields = new ArrayList<>(); /** * Constructor to make multipart requests * * @param url URL to send request to * @param connectTimeout connection timeout * @param readTimeout read timeout */ public Multipart(String url, int connectTimeout, int readTimeout) { super(url, connectTimeout, readTimeout); } @Override protected Multipart doConnect() { try { boundary = "JavaLite-HTTP-"+ UUID.randomUUID() ; connection.setUseCaches(false); connection.setDoOutput(true); // indicates POST method connection.setDoInput(true); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); connection.setInstanceFollowRedirects(redirect); outputStream = connection.getOutputStream(); writer = new PrintWriter(new OutputStreamWriter(outputStream), true); sendData(); finish(); return this; } catch (Exception e) { throw new HttpException("Failed URL: " + url, e); } } private void sendData() { for (FormField f : formFields) { if(f.isFile()){ sendFile((FileField)f); }else{ sendField(f); } } } private void finish(){ writer.append(LINE_FEED); writer.append("--").append(boundary).append("--").append(LINE_FEED); writer.close(); } private void sendField(FormField f) { writer.append("--").append(boundary).append(LINE_FEED); writer.append("Content-Disposition: form-data; name=\"").append(f.getName()).append("\"").append(LINE_FEED); writer.append("Content-Type: text/plain" ).append(LINE_FEED); writer.append(LINE_FEED); writer.append(f.getValue()).append(LINE_FEED); writer.flush(); } private void sendFile(FileField f) { try { String fileName = f.getFile().getName(); writer.append("--").append(boundary).append(LINE_FEED); writer.append("Content-Disposition: form-data; name=\"").append(f.getName()).append("\"; filename=\"").append(fileName).append("\"").append(LINE_FEED); writer.append("Content-Type: ").append(URLConnection.guessContentTypeFromName(fileName)).append(LINE_FEED); writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED); writer.append(LINE_FEED); writer.flush(); FileInputStream inputStream = new FileInputStream(f.getFile()); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.flush(); inputStream.close(); writer.append(LINE_FEED); writer.flush(); } catch (Exception e) { throw new HttpException(e); } } /** * Adds a form field to the request * * @param field instance of form field * @return self */ public Multipart field(FormField field){ formFields.add(field); return this; } /** * Convenience method to add a form field to the request. * * @param name name of field * @param value value of field * @return self */ public Multipart field(String name, String value){ formFields.add(new FormField(name, value)); return this; } /** * Convenience method to add multiple fields to the request. * Names and values alternate: name1, value1, name2, value2, etc. * * @param namesAndValues names/values of multiple fields to be added to the request. * @return self */ public Multipart fields(String ... namesAndValues){ if(namesAndValues == null ){ throw new NullPointerException("'names and values' cannot be null"); } if(namesAndValues.length % 2 != 0){ throw new IllegalArgumentException("mus pas even number of arguments"); } for (int i = 0; i < namesAndValues.length - 1; i += 2) { if (namesAndValues[i] == null) throw new IllegalArgumentException("parameter names cannot be nulls"); formFields.add(new FormField(namesAndValues[i], namesAndValues[i + 1])); } return this; } /** * Convenience method to add a file fields to the request. * * @param fieldName name of field * @param filePath fully qualified path to a file. * @return self. */ public Multipart file(String fieldName, String filePath ){ formFields.add(new FileField(fieldName, new File(filePath))); return this; } public static void main(String[] args){ //use kitchensink Multipart mp = Http.multipart("http://localhost:8080/upload/save") .field("name1", "val1") .file("file1", "/home/igor/tmp/test.txt"); System.out.println(mp.headers()); } }