android向服务器上传multipart/form-data文件(upload using multipart post using httpclient in android)

来源:互联网 发布:稚优泉水母面膜 知乎 编辑:程序博客网 时间:2024/05/21 22:52

转载自:http://blog.rafaelsanches.com/2011/01/29/upload-using-multipart-post-using-httpclient-in-android/

AsyncHttpClient也是参考它实现的。


A very common caveat, when doing android applications, is fighting to keep the APK size small.

Many applications need the ability to upload binary data to their server and when you arrive there you see that the android SDK doesn’t have the http-client libraries to send multipart posts.

The easiest way is to include the JAR for httpmime and apache_mime4j, but it takes way too much space; 300kb.

To overcome this you can implement your own HttpEntity. In this way the code is:

public class SimpleMultipartEntity implements HttpEntity {    private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"        .toCharArray();    private String boundary = null;    ByteArrayOutputStream out = new ByteArrayOutputStream();    boolean isSetLast = false;    boolean isSetFirst = false;    public SimpleMultipartEntity() {        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)]);        }        this.boundary = buf.toString();    }    public void writeFirstBoundaryIfNeeds(){        if(!isSetFirst){            try {                out.write(("--" + boundary + "\r\n").getBytes());            } catch (final IOException e) {                Log.e(Constants.TAG, e.getMessage(), e);            }        }        isSetFirst = true;    }    public void writeLastBoundaryIfNeeds() {        if(isSetLast){            return ;        }        try {            out.write(("\r\n--" + boundary + "--\r\n").getBytes());        } catch (final IOException e) {            Log.e(Constants.TAG, e.getMessage(), e);        }        isSetLast = true;    }    public void addPart(final String key, final String value) {        writeFirstBoundaryIfNeeds();        try {            out.write(("Content-Disposition: form-data; name=\"" +key+"\"\r\n").getBytes());            out.write("Content-Type: text/plain; charset=UTF-8\r\n".getBytes());            out.write("Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes());            out.write(value.getBytes());            out.write(("\r\n--" + boundary + "\r\n").getBytes());        } catch (final IOException e) {            Log.e(Constants.TAG, e.getMessage(), e);        }    }    public void addPart(final String key, final String fileName, final InputStream fin){        addPart(key, fileName, fin, "application/octet-stream");    }    public void addPart(final String key, final String fileName, final InputStream fin, String type){        writeFirstBoundaryIfNeeds();        try {            type = "Content-Type: "+type+"\r\n";            out.write(("Content-Disposition: form-data; name=\""+ key+"\"; filename=\"" + fileName + "\"\r\n").getBytes());            out.write(type.getBytes());            out.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) {                out.write(tmp, 0, l);            }            out.flush();        } catch (final IOException e) {            Log.e(Constants.TAG, e.getMessage(), e);        } finally {            try {                fin.close();            } catch (final IOException e) {                Log.e(Constants.TAG, e.getMessage(), e);            }        }    }    public void addPart(final String key, final File value) {        try {            addPart(key, value.getName(), new FileInputStream(value));        } catch (final FileNotFoundException e) {            Log.e(Constants.TAG, e.getMessage(), e);        }    }    @Override    public long getContentLength() {        writeLastBoundaryIfNeeds();        return out.toByteArray().length;    }    @Override    public Header getContentType() {        return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + boundary);    }    @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 {        outstream.write(out.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() throws IOException,    UnsupportedOperationException {        return new ByteArrayInputStream(out.toByteArray());    }}


0 0