ANDROID使用MULTIPARTENTITYBUILDER实现类似FORM表单提交方式的文件上传

最近在做 Android 端文件上传,要求采用 form 表单的方式提交,项目使用的 afinal 框架有文件上传功能,但是始终无法与php写的服务端对接上,无法上传成功。读源码发现:afinal 使用了某大神写的 MultipartEntity.java 生成 form 表单内容,然而生成的内容格式不够标准,而且还存在诸多问题,如:首先将所有文件读入到内存,再生成字节流写入到 socket。那么问题来了:如果是几百MB的文件怎么办?

几番搜索,受到 这篇文章(已被我转载,但是示例代码已过期)的启发,我辗转找到了 Apache 源码 httpcomponents-client-4.3.6-src.zip,在一个示例里面发现了一个重要的组件 MultipartEntityBuilder, 可以生成 form 表单格式的 HttpEntity, 有了 HttpEntity, 无论你是什么 http 框架,应该都可以使用。

不知道怎么使用?like this:

HttpPost httppost = new HttpPost(url);
...
httppost.setEntity(makeMultipartEntity(params, files));
HttpResponse response = getHttpClient().execute(httppost);
...

private static HttpClient mClient;
private static HttpClient getHttpClient() {
    if(mClient == null) {
        //if(Build.VERSION.SDK_INT >= 9);    //将不走本类的Case,基于HttpURLConnection
        if(Build.VERSION.SDK_INT >= 8) {
            mClient = AndroidHttpClient.newInstance(getUserAgent());
        }else {
            mClient = new DefaultHttpClient();
        }
    }
    return mClient;
}

MultipartEntityBuilder 用法整理如下:

需要用到 httpcomponents-client-4.3.6-bin.zip 中的 httpmime-4.3.6.jar 和 httpcore-4.3.3.jar

public static HttpEntity makeMultipartEntity(List<NameValuePair> params, final Map<String, File> files) {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.setMode(HttpMultipartMode.STRICT);    //如果有SocketTimeoutException等情况,可修改这个枚举
    //builder.setCharset(Charset.forName("UTF-8"));    //不要用这个,会导致服务端接收不到参数
    if (params != null && params.size() > 0) {
        for (NameValuePair p : params) {
            builder.addTextBody(p.getName(), p.getValue(), ContentType.TEXT_PLAIN.withCharset("UTF-8"));
        }
    }
    if (files != null && files.size() > 0) {
        Set<Entry<String, File>> entries = files.entrySet();
        for (Entry<String, File> entry : entries) {
            builder.addPart(entry.getKey(), new FileBody(entry.getValue()));
        }
    }
    return builder.build();
}

另附上 Apache 示例,可在 httpcomponents-client-4.3.6-bin.zip 中找到。

/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */
package org.apache.http.examples.entity.mime;

import java.io.File;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Example how to use multipart/form encoded POST request.
 */
public class ClientMultipartFormPost {

    public static void main(String[] args) throws Exception {
        if (args.length != 1)  {
            System.out.println("File path not given");
            System.exit(1);
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost("http://localhost:8080" +
                    "/servlets-examples/servlet/RequestInfoExample");

            FileBody bin = new FileBody(new File(args[0]));
            StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);

            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    .addPart("bin", bin)
                    .addPart("comment", comment)
                    .build();

            httppost.setEntity(reqEntity);

            System.out.println("executing request " + httppost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    System.out.println("Response content length: " + resEntity.getContentLength());
                }
                EntityUtils.consume(resEntity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}
时间: 2024-10-08 11:13:23

ANDROID使用MULTIPARTENTITYBUILDER实现类似FORM表单提交方式的文件上传的相关文章

使用ajax提交form表单,包括ajax文件上传 转http://www.cnblogs.com/zhuxiaojie/p/4783939.html

使用ajax提交form表单,包括ajax文件上传 前言 使用ajax请求数据,很多人都会,比如说: $.post(path,{data:data},function(data){ ... },"json"); 又或者是这样的ajax $.ajax({ url:"${pageContext.request.contextPath}/public/testupload", type:"post", data:{username:username},

使用ajax提交form表单,包括ajax文件上传

前言 使用ajax请求数据,很多人都会,比如说: $.post(path,{data:data},function(data){ ... },"json"); 又或者是这样的ajax $.ajax({ url:"${pageContext.request.contextPath}/public/testupload", type:"post", data:{username:username}, success:function(data){ w

ajax提交表单、ajax实现文件上传

ajax提交表单.ajax实现文件上传,有需要的朋友可以参考下. 方式一:利用from表单的targer属性 + 隐藏的iframe 达到类似效果, 支持提交含有文件和普通数据的复杂表单 方式二:使用jquery的$.ajax({..}), 支持提交普通表单,但不支持含有文件的复杂表单; ($.post 或 $.get底层用的都是$.ajax) 方式三:使用jquery插件ajaxFileUpload.js, 支持上传文件,但不支持提交表单 方式四:使用jquery.from.js,支持提交同时

c#代码,模拟form表单发送post请求,上传文件(并带其他参数)

本人对post理解不深,前段时间遇到一个需要用c#代码发送post请求上传文件的业务,于是参考了几篇帖子,加上自身实践写出了如下代码.写的比较low 望各位大大指正^_^. 业务需求: 对方给了一个接口,让传四个参数分别为"modelId.fileContent.updateTime.encrypt" 其中modelId.updateTime.encrypt 都是普通的字符串类型.fileContent则是二进制文件 我实在是不了解post的相关知识,平时只是普通的用法,没有深层看过相

Linux curl 模拟form表单提交信息和文件

curl是一个命令行方式下传输数据的开源传输工具,支持多种协议:FTP.HTTP.HTTPS.IMAP.POP3.TELNET等,功能超级强大. 我今天想说的是程序开发中常用的模拟Form提交 1.GET提交 特别简单直接写url里面 2.POST提交    通过 --data/-d 方式指定使用POST方式传递数据 3.模拟form表单提交文件  --form/-F 模拟form表单提交文件 这个命令超级好用,再也不用为了写上传接口,而被迫写一个Form表单了 "[email protecte

form表单提交方式

无刷新页面提交表单 表单可实现无刷新页面提交,无需页面跳转,如下,通过一个隐藏的iframe实现,form表单的target设置为iframe的name名称,form提交目标位当前页面iframe则不会刷新页面 <form action="/url.do" method="post" target="targetIfr"> <input type="text" name="name"/&g

学习java前端 两种form表单提交方式

第一种:原生方式 注意点:button标签的style为submit <form action="/trans/doTrans.do" method="post"> 转出卡号:${cardNo} <br> 转出卡号余额:${balance}元 <br> <br> 转入卡号:<input name="checkInCardNo" type="text"> <br&

摒弃FORM表单上传图片,异步批量上传照片

之前作图像处理一直在用form表单做图片数据传输, 个人感觉low到爆炸而且用户体验极差,现在介绍一个一部批量上传图片的小技巧,忘帮助他人的同时也警醒自己在代码的编写时不要只顾着方便,也要考虑代码的健壮性个用户体验度. 异步提交照片需要一个CSS文件和相应jqurey文件.如图: HTML具体代码如下 <!DOCTYPE html> {# 加载静态文件 #} {% load static %} <html lang="en"> <head> <

ajax提交表单,并且可以支持文件上传

当我们提交表单但是又不想要刷新页面的时候就可以考虑使用ajax来实现提交功能,但是这有个局限就是当有文件上传的时候是行不通的,下面借助于jquery.form可以很方便满足我们的需求. 1.表单写法: <form class="ui form error-page" id="error_page" method="post" action="{{ url('web/save/error-page') }}" enctyp