package net.hockeyapp.android.utils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Random; /** * <h3>Description</h3> * * To avoid external apache library "httpmime" this is a simple implementation for a MultipartEntity. * Please note that first all key value pairs have to be written and then at least one file part has to be added. * Otherwise the boundaries are not written correctly. * */ public class SimpleMultipartEntity { private final static char[] BOUNDARY_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); private boolean mIsSetLast; private boolean mIsSetFirst; private ByteArrayOutputStream mOut; private String mBoundary; public SimpleMultipartEntity() { this.mIsSetFirst = false; this.mIsSetLast = false; this.mOut = new ByteArrayOutputStream(); /** Create boundary String */ final StringBuffer buffer = new StringBuffer(); final Random rand = new Random(); for (int i = 0; i < 30; i++) { buffer.append(BOUNDARY_CHARS[rand.nextInt(BOUNDARY_CHARS.length)]); } this.mBoundary = buffer.toString(); } public String getBoundary() { return mBoundary; } public void writeFirstBoundaryIfNeeds() throws IOException { if (!mIsSetFirst) { mOut.write(("--" + mBoundary + "\r\n").getBytes()); } mIsSetFirst = true; } public void writeLastBoundaryIfNeeds() { if (mIsSetLast) { return; } try { mOut.write(("\r\n--" + mBoundary + "--\r\n").getBytes()); } catch (final IOException e) { e.printStackTrace(); } mIsSetLast = true; } public void addPart(final String key, final String value) throws IOException { writeFirstBoundaryIfNeeds(); mOut.write(("Content-Disposition: form-data; name=\"" + key + "\"\r\n").getBytes()); mOut.write("Content-Type: text/plain; charset=UTF-8\r\n".getBytes()); mOut.write("Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes()); mOut.write(value.getBytes()); mOut.write(("\r\n--" + mBoundary + "\r\n").getBytes()); } public void addPart(final String key, final File value, boolean lastFile) throws IOException { addPart(key, value.getName(), new FileInputStream(value), lastFile); } public void addPart(final String key, final String fileName, final InputStream fin, boolean lastFile) throws IOException { addPart(key, fileName, fin, "application/octet-stream", lastFile); } public void addPart(final String key, final String fileName, final InputStream fin, String type, boolean lastFile) throws IOException { writeFirstBoundaryIfNeeds(); try { type = "Content-Type: " + type + "\r\n"; mOut.write(("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + fileName + "\"\r\n").getBytes()); mOut.write(type.getBytes()); mOut.write("Content-Transfer-Encoding: binary\r\n\r\n".getBytes()); final byte[] tmp = new byte[4096]; int l = 0; while ((l = fin.read(tmp)) != -1) { mOut.write(tmp, 0, l); } mOut.flush(); if (lastFile) { /** This is the last file: write last boundary. */ writeLastBoundaryIfNeeds(); } else { /** Another file will follow: write normal boundary. */ mOut.write(("\r\n--" + mBoundary + "\r\n").getBytes()); } } finally { try { fin.close(); } catch (final IOException e) { e.printStackTrace(); } } } public long getContentLength() { writeLastBoundaryIfNeeds(); return mOut.toByteArray().length; } public String getContentType() { return "multipart/form-data; boundary=" + getBoundary(); } public ByteArrayOutputStream getOutputStream() { writeLastBoundaryIfNeeds(); return mOut; } }