在没有外部库的情况下发送多部分POST数据

时间:2014-04-03 02:41:08

标签: java android httpurlconnection apache-httpclient-4.x

我的Android应用程序架构基于DefaultHttpClient。大约2天前,我标题他们正在改进HttpURLConnection,我正要改变整个架构以使用它,但似乎代码重写太多了,所以我坚持DefaultHttpClient

现在我必须上传一个multipart实体,而且我一直在阅读有关从mime添加一个名为Apache的外部库的信息,该文件恰好是已弃用

我的问题是,有没有办法使用multipartAndroid Java发送SDK实体?因为如果没有,那么我想我会把它全部更改为HttpURLConnection

1 个答案:

答案 0 :(得分:0)

你可以尝试我为我的项目编写的一些类。多部分表单类是一个非常简单的实现,但它应该很容易破解,以适应发送数据数组或任何你需要的。

/**
 * Used to provide an interface for sending post data of various types.
 */
public interface PostData {
    /**
     * Add the specified field to the post data.
     *
     * @param name The name or title of the field.
     * @param value The value of the field.
     * @return This object (for streamed programming)
     */
    public PostData addField(String name, String value);
    /**
     * End the data.
     */
    public PostData end();

    public String getContentType();
    public String toString();
    public int getLength();
}


/**
 * Generate a multi-part form to post data.
 */
public static class MultiPartForm implements PostData {
    private final static String boundary = "AaBbC0xQrpqqqqqqqq";
    private StringBuilder sb = new StringBuilder();

    public PostData addField(String name, String value) {
        sb.append("--")
            .append(boundary)
            .append("\nContent-Disposition: form-data; name='")
            .append(name)
            .append("'\n\n")
            .append(value)
            .append("\n");
        return this;
    }

    public PostData end() {
        sb.append("--").append(boundary).append("--");
        return this;
    }

    public final String getContentType() {
        return "multipart/form-data;boundary=" + boundary;
    }

    public String toString() {
        return sb.toString();
    }

    public int getLength() {
        return sb.length();
    }
}


/**
 * Creates URL encoded data.
 * Does not include the question mark at the beginning of the string.
 */
public static class UrlEncodedData implements PostData {
    private StringBuilder sb = new StringBuilder();

    public PostData addField(String name, String value) {
        if (sb.length() > 0) {
            sb.append("&");
        }
        try {
            sb.append(URLEncoder.encode(name, "UTF-8"))
                .append("=")
                .append(URLEncoder.encode(value, "UTF-8"));
        // Shouldn't ever happen.
        } catch (java.io.UnsupportedEncodingException e) {}
        return this;
    }

    public PostData end() {
        return this;
    }

    public final String getContentType() {
        return "application/x-www-form-urlencoded";
    }

    public String toString() {
        return sb.toString();
    }

    public int getLength() {
        return sb.length();
    }
}

除此之外,我还创建了一种方法,使检索数据更加简单。我在这个方法中使用了HttpURLConnection,但是对于如何使用DefaultHttpClient做同样的事情应该非常简单。请注意,它是同步的,因此您必须在另一个线程中调用它:

/**
 * Loads a specified URL with the params incoded in the post.
 * 
 * @throws Exception For numerous reasons.
 * @param url The base URL to connect to.
 * @param data A PostData object to fetch. Specifiy null for a GET request.
 * @return The result.
 */
public static String loadUrl(final String url, final PostData data)
        throws Exception {
    HttpURLConnection urlConnection = null;
    BufferedReader br = null;
    final StringBuilder result = new StringBuilder();

    try {
        urlConnection = (HttpURLConnection)new URL(url).openConnection();

        if (data != null) {
            urlConnection.setRequestMethod("POST");;
            urlConnection.setRequestProperty("Content-Type", data.getContentType());
            urlConnection.setRequestProperty("Content-Length",
                Integer.toString(data.getLength()));
            urlConnection.setDoOutput(true);

            DataOutputStream dos = new DataOutputStream(
                urlConnection.getOutputStream());
            dos.writeBytes(data.toString());
            dos.flush();
            dos.close();

            urlConnection.connect();
        }

        br = new BufferedReader(
            new InputStreamReader(urlConnection.getInputStream()));

        String line;
        while ((line = br.readLine()) != null) {
            result.append(line);
        }
    } finally {
        try { urlConnection.disconnect(); } catch (Exception e) {}
        try { br.close(); } catch (Exception e) {}
    }

    return result.toString();
}

用法非常简单:

Utils.loadUrl("someApi.com/foobar/"
    new Utils.MultiPartForm()
        .addField("first_name", "John")
        .addField("last_name", "Doe")
        .end());