Android Open Source - fh-android-sdk Simple Multipart Entity






From Project

Back to project page fh-android-sdk.

License

The source code is released under:

Copyright (c) 2014 FeedHenry Ltd, All Rights Reserved. Please refer to your contract with FeedHenry for the software license agreement. If you do not have a contract, you do not have a license to use...

If you think the Android project fh-android-sdk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
    Android Asynchronous Http Client/*from  w ww  .j  av a2s. c  o  m*/
    Copyright (c) 2011 James Smith <james@loopj.com>
    http://loopj.com

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/*
    This code is taken from Rafael Sanches' blog.
    http://blog.rafaelsanches.com/2011/01/29/upload-using-multipart-post-using-httpclient-in-android/
*/

package com.loopj.android.http;

import android.util.Log;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicHeader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Simplified multipart entity mainly used for sending one or more files.
 */
class SimpleMultipartEntity implements HttpEntity {

    private static final String LOG_TAG = "SimpleMultipartEntity";

    private static final String STR_CR_LF = "\r\n";
    private static final byte[] CR_LF = STR_CR_LF.getBytes();
    private static final byte[] TRANSFER_ENCODING_BINARY =
        ("Content-Transfer-Encoding: binary" + STR_CR_LF).getBytes();

    private final static char[] MULTIPART_CHARS =
        "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

    private final String boundary;
    private final byte[] boundaryLine;
    private final byte[] boundaryEnd;
    private boolean isRepeatable;

    private final List<FilePart> fileParts = new ArrayList();

    // The buffer we use for building the message excluding files and the last
    // boundary
    private final ByteArrayOutputStream out = new ByteArrayOutputStream();

    private final ResponseHandlerInterface progressHandler;

    private int bytesWritten;

    private int totalSize;

    public SimpleMultipartEntity(ResponseHandlerInterface progressHandler) {
        final StringBuilder buf = new StringBuilder();
        final Random rand = new Random();
        for (int i = 0; i < 30; i++) {
            buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
        }

        boundary = buf.toString();
        boundaryLine = ("--" + boundary + STR_CR_LF).getBytes();
        boundaryEnd = ("--" + boundary + "--" + STR_CR_LF).getBytes();

        this.progressHandler = progressHandler;
    }

    public void addPart(String key, String value, String contentType) {
        try {
            out.write(boundaryLine);
            out.write(createContentDisposition(key));
            out.write(createContentType(contentType));
            out.write(CR_LF);
            out.write(value.getBytes());
            out.write(CR_LF);
        } catch (final IOException e) {
            // Shall not happen on ByteArrayOutputStream
            Log.e(LOG_TAG, "addPart ByteArrayOutputStream exception", e);
        }
    }

    public void addPart(String key, String value) {
        addPart(key, value, "text/plain; charset=UTF-8");
    }

    public void addPart(String key, File file) {
        addPart(key, file, null);
    }

    public void addPart(String key, File file, String type) {
        fileParts.add(new FilePart(key, file, normalizeContentType(type)));
    }

    public void addPart(String key, String streamName, InputStream inputStream, String type)
            throws IOException {

        out.write(boundaryLine);

        // Headers
        out.write(createContentDisposition(key, streamName));
        out.write(createContentType(type));
        out.write(TRANSFER_ENCODING_BINARY);
        out.write(CR_LF);

        // Stream (file)
        final byte[] tmp = new byte[4096];
        int l;
        while ((l = inputStream.read(tmp)) != -1) {
            out.write(tmp, 0, l);
        }

        out.write(CR_LF);
        out.flush();

        AsyncHttpClient.silentCloseOutputStream(out);
    }

    private String normalizeContentType(String type) {
       return type == null ? RequestParams.APPLICATION_OCTET_STREAM : type;
    }

    private byte[] createContentType(String type) {
        String result = "Content-Type: " + normalizeContentType(type) + STR_CR_LF;
        return result.getBytes();
    }

    private byte[] createContentDisposition(String key) {
        return ("Content-Disposition: form-data; name=\"" + key + "\"" + STR_CR_LF)
            .getBytes();
    }

    private byte[] createContentDisposition(String key, String fileName) {
        return ("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + fileName + "\"" + STR_CR_LF)
            .getBytes();
    }

    private void updateProgress(int count) {
        bytesWritten += count;
        progressHandler.sendProgressMessage(bytesWritten, totalSize);
    }

    private class FilePart {
        public File file;
        public byte[] header;

        public FilePart(String key, File file, String type) {
            header = createHeader(key, file.getName(), type);
            this.file = file;
        }

        private byte[] createHeader(String key, String filename, String type) {
            ByteArrayOutputStream headerStream = new ByteArrayOutputStream();
            try {
                headerStream.write(boundaryLine);

                // Headers
                headerStream.write(createContentDisposition(key, filename));
                headerStream.write(createContentType(type));
                headerStream.write(TRANSFER_ENCODING_BINARY);
                headerStream.write(CR_LF);
            } catch (IOException e) {
                // Can't happen on ByteArrayOutputStream
                Log.e(LOG_TAG, "createHeader ByteArrayOutputStream exception", e);
            }
            return headerStream.toByteArray();
        }

        public long getTotalLength() {
            long streamLength = file.length() + CR_LF.length;
            return header.length + streamLength;
        }

        public void writeTo(OutputStream out) throws IOException {
            out.write(header);
            updateProgress(header.length);

            FileInputStream inputStream = new FileInputStream(file);
            final byte[] tmp = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(tmp)) != -1) {
                out.write(tmp, 0, bytesRead);
                updateProgress(bytesRead);
            }
            out.write(CR_LF);
            updateProgress(CR_LF.length);
            out.flush();
            AsyncHttpClient.silentCloseInputStream(inputStream);
        }
    }

    // The following methods are from the HttpEntity interface

    @Override
    public long getContentLength() {
        long contentLen = out.size();
        for (FilePart filePart : fileParts) {
            long len = filePart.getTotalLength();
            if (len < 0) {
                return -1; // Should normally not happen
            }
            contentLen += len;
        }
        contentLen += boundaryEnd.length;
        return contentLen;
    }

    @Override
    public Header getContentType() {
        return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
    }

    @Override
    public boolean isChunked() {
        return false;
    }

    public void setIsRepeatable(boolean isRepeatable) {
        this.isRepeatable = isRepeatable;
    }

    @Override
    public boolean isRepeatable() {
        return isRepeatable;
    }

    @Override
    public boolean isStreaming() {
        return false;
    }

    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
        bytesWritten = 0;
        totalSize = (int) getContentLength();
        out.writeTo(outstream);
        updateProgress(out.size());

        for (FilePart filePart : fileParts) {
            filePart.writeTo(outstream);
        }
        outstream.write(boundaryEnd);
        updateProgress(boundaryEnd.length);
    }

    @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 {
        throw new UnsupportedOperationException(
                "getContent() is not supported. Use writeTo() instead.");
    }
}




Java Source Code List

com.feedhenry.fhandroidexampleapp.FHActActivity.java
com.feedhenry.fhandroidexampleapp.FHAndroidExampleActivity.java
com.feedhenry.fhandroidexampleapp.FHAuthActivity.java
com.feedhenry.fhandroidexampleapp.FHLoginActivity.java
com.feedhenry.fhandroidexampleapp.FHSyncActivity.java
com.feedhenry.fhandroidexampleapp.FhUtil.java
com.feedhenry.fhandroidexampleapp.ItemDetailsActivity.java
com.feedhenry.fhandroidexampleapp.SyncCollisionResolveActivity.java
com.feedhenry.fhandroidexampleapp.SyncCollisionsListActivity.java
com.feedhenry.sdk.CloudProps.java
com.feedhenry.sdk.FHActCallback.java
com.feedhenry.sdk.FHAct.java
com.feedhenry.sdk.FHHttpClient.java
com.feedhenry.sdk.FHRemote.java
com.feedhenry.sdk.FHResponse.java
com.feedhenry.sdk.FH.java
com.feedhenry.sdk.api.FHActRequest.java
com.feedhenry.sdk.api.FHAuthRequest.java
com.feedhenry.sdk.api.FHCloudRequest.java
com.feedhenry.sdk.api.FHInitializeRequest.java
com.feedhenry.sdk.exceptions.FHInvalidActionException.java
com.feedhenry.sdk.exceptions.FHNotReadyException.java
com.feedhenry.sdk.oauth.FHOAuthIntent.java
com.feedhenry.sdk.oauth.FHOAuthWebView.java
com.feedhenry.sdk.sync.FHSyncClient.java
com.feedhenry.sdk.sync.FHSyncConfig.java
com.feedhenry.sdk.sync.FHSyncDataRecord.java
com.feedhenry.sdk.sync.FHSyncDataset.java
com.feedhenry.sdk.sync.FHSyncListener.java
com.feedhenry.sdk.sync.FHSyncNotificationHandler.java
com.feedhenry.sdk.sync.FHSyncPendingRecord.java
com.feedhenry.sdk.sync.FHSyncUtils.java
com.feedhenry.sdk.sync.NotificationMessage.java
com.feedhenry.sdk.utils.FHLog.java
com.feedhenry.starter.FHStarterActivity.java
com.loopj.android.http.AsyncHttpClient.java
com.loopj.android.http.AsyncHttpRequest.java
com.loopj.android.http.AsyncHttpResponseHandler.java
com.loopj.android.http.Base64DataException.java
com.loopj.android.http.Base64OutputStream.java
com.loopj.android.http.Base64.java
com.loopj.android.http.BaseJsonHttpResponseHandler.java
com.loopj.android.http.BinaryHttpResponseHandler.java
com.loopj.android.http.DataAsyncHttpResponseHandler.java
com.loopj.android.http.FileAsyncHttpResponseHandler.java
com.loopj.android.http.JsonHttpResponseHandler.java
com.loopj.android.http.JsonStreamerEntity.java
com.loopj.android.http.MyRedirectHandler.java
com.loopj.android.http.MySSLSocketFactory.java
com.loopj.android.http.PersistentCookieStore.java
com.loopj.android.http.PreemtiveAuthorizationHttpRequestInterceptor.java
com.loopj.android.http.RangeFileAsyncHttpResponseHandler.java
com.loopj.android.http.RequestHandle.java
com.loopj.android.http.RequestParams.java
com.loopj.android.http.ResponseHandlerInterface.java
com.loopj.android.http.RetryHandler.java
com.loopj.android.http.SerializableCookie.java
com.loopj.android.http.SimpleMultipartEntity.java
com.loopj.android.http.SyncHttpClient.java
com.loopj.android.http.TextHttpResponseHandler.java
org.json.fh.CDL.java
org.json.fh.CookieList.java
org.json.fh.Cookie.java
org.json.fh.HTTPTokener.java
org.json.fh.HTTP.java
org.json.fh.JSONArray.java
org.json.fh.JSONException.java
org.json.fh.JSONObject.java
org.json.fh.JSONString.java
org.json.fh.JSONStringer.java
org.json.fh.JSONTokener.java
org.json.fh.JSONWriter.java
org.json.fh.XMLTokener.java
org.json.fh.XML.java