Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2014-2015 bboyfeiyu@gmail.com, Inc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package bbd.basesimplenet.net.entity; import android.text.TextUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.message.BasicHeader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Random; /** * POST??? : http://blog.csdn.net/bboyfeiyu/article/details/41863951. * <p> * Android?Entity,??????, * ???httpmime.jar?. * </p> * * @author Dengb */ public class MultipartEntity implements HttpEntity { public static final String ABCDEFGHIJKLMNOPQRSTUVWXYZ_ABCDEFGHIJKLMNOPQRSTUVWXYZ = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private final static char[] MULTIPART_CHARS = ABCDEFGHIJKLMNOPQRSTUVWXYZ_ABCDEFGHIJKLMNOPQRSTUVWXYZ .toCharArray(); /** * ? */ private final String NEW_LINE_STR = "\r\n"; private final String CONTENT_TYPE = "Content-Type: "; private final String CONTENT_DISPOSITION = "Content-Disposition: "; /** * ? */ private final String TYPE_TEXT_CHARSET = "text/plain; charset=UTF-8"; /** * ?? */ private final String TYPE_OCTET_STREAM = "application/octet-stream"; /** * ? */ private final byte[] BINARY_ENCODING = "Content-Transfer-Encoding: binary\r\n\r\n".getBytes(); /** * ? */ private final byte[] BIT_ENCODING = "Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes(); /** * */ private String mBoundary = null; /** * ? */ ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream(); public MultipartEntity() { this.mBoundary = generateBoundary(); } /** * ? * * @return */ private final String generateBoundary() { final StringBuffer buf = new StringBuffer(); final Random rand = new Random(); for (int i = 0; i < 30; i++) { buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]); } return buf.toString(); } /** * ? * * @throws IOException */ private void writeFirstBoundary() throws IOException { mOutputStream.write(("--" + mBoundary + "\r\n").getBytes()); } /** * ? * * @param paramName * @param value */ public void addStringPart(final String paramName, final String value) { writeToOutputStream(paramName, value.getBytes(), TYPE_TEXT_CHARSET, BIT_ENCODING, ""); } /** * ?? * * @param paramName * @param rawData * @param type * @param encodingBytes * @param fileName */ private void writeToOutputStream(String paramName, byte[] rawData, String type, byte[] encodingBytes, String fileName) { try { writeFirstBoundary(); mOutputStream.write((CONTENT_TYPE + type + NEW_LINE_STR).getBytes()); mOutputStream.write(getContentDispositionBytes(paramName, fileName)); mOutputStream.write(encodingBytes); mOutputStream.write(rawData); mOutputStream.write(NEW_LINE_STR.getBytes()); } catch (final IOException e) { e.printStackTrace(); } } /** * ?, Bitmap?? * * @param paramName * @param rawData */ public void addBinaryPart(String paramName, final byte[] rawData) { writeToOutputStream(paramName, rawData, TYPE_OCTET_STREAM, BINARY_ENCODING, "no-file"); } /** * ?,? * * @param key * @param file */ public void addFilePart(final String key, final File file) { InputStream fin = null; try { fin = new FileInputStream(file); writeFirstBoundary(); final String type = CONTENT_TYPE + TYPE_OCTET_STREAM + NEW_LINE_STR; mOutputStream.write(getContentDispositionBytes(key, file.getName())); mOutputStream.write(type.getBytes()); mOutputStream.write(BINARY_ENCODING); final byte[] tmp = new byte[4096]; int len = 0; while ((len = fin.read(tmp)) != -1) { mOutputStream.write(tmp, 0, len); } mOutputStream.flush(); } catch (final IOException e) { e.printStackTrace(); } finally { closeSilently(fin); } } private void closeSilently(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (final IOException e) { e.printStackTrace(); } } private byte[] getContentDispositionBytes(String paramName, String fileName) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(CONTENT_DISPOSITION + "form-data; name=\"" + paramName + "\""); // ?filename?,?? if (!TextUtils.isEmpty(fileName)) { stringBuilder.append("; filename=\"" + fileName + "\""); } return stringBuilder.append(NEW_LINE_STR).toString().getBytes(); } @Override public long getContentLength() { return mOutputStream.toByteArray().length; } @Override public Header getContentType() { return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + mBoundary); } @Override public boolean isChunked() { return false; } @Override public boolean isRepeatable() { return false; } @Override public boolean isStreaming() { return false; } @Override public void writeTo(final OutputStream outstream) throws IOException { // ?? final String endString = "--" + mBoundary + "--\r\n"; // ? mOutputStream.write(endString.getBytes()); // outstream.write(mOutputStream.toByteArray()); } @Override public Header getContentEncoding() { return null; } @Override public void consumeContent() throws IOException, UnsupportedOperationException { if (isStreaming()) { throw new UnsupportedOperationException("Streaming entity does not implement #consumeContent()"); } } @Override public InputStream getContent() { return new ByteArrayInputStream(mOutputStream.toByteArray()); } }