Android模拟 HTTP multipart/form-data 请求协议信息实现图片上传

问题:

Android应用中,当遇到填写用户信息、发表评论等操作,不可避免会遇到“form表单操作”(类似web form操作)上传图片的功能。

在这种情况下,使用Android的HTTPConnection/ ApacheHTTP 通过POST 和GET的方式就实现不了。

解决方法:


Android客户端通过模拟 HTTP multipart/form-data 请求协议信息实现图片上传。

/**  
 * 文件名称:UploadImage.java  
 *  
 * 版权信息:Apache License, Version 2.0  
 *  
 * 功能描述:实现图片文件上传。  
 *  
 * 创建日期:2011-5-10  
 *  
 * 作者:Bert Lee  
 */   
   
/*  
 * 修改历史:  
 */   
public class UploadImage {   
    String multipart_form_data = "multipart/form-data";   
    String twoHyphens = "--";   
    String boundary = "****************fD4fH3gL0hK7aI6";    // 数据分隔符    
    String lineEnd = System.getProperty("line.separator");    // The value is "\r\n" in Windows.    
       
    /*  
     * 上传图片内容,格式请参考HTTP 协议格式。  
     * 人人网Photos.upload中的”程序调用“http://wiki.dev.renren.com/wiki/Photos.upload#.E7.A8.8B.E5.BA.8F.E8.B0.83.E7.94.A8  
     * 对其格式解释的非常清晰。  
     * 格式如下所示:  
     * --****************fD4fH3hK7aI6  
     * Content-Disposition: form-data; name="upload_file"; filename="apple.jpg"  
     * Content-Type: image/jpeg  
     *  
     * 这儿是文件的内容,二进制流的形式  
     */   
    private void addImageContent(Image[] files, DataOutputStream output) {   
        for(Image file : files) {   
            StringBuilder split = new StringBuilder();   
            split.append(twoHyphens + boundary + lineEnd);   
            split.append("Content-Disposition: form-data; name=\"" + file.getFormName() + "\"; filename=\"" + file.getFileName() + "\"" + lineEnd);   
            split.append("Content-Type: " + file.getContentType() + lineEnd);   
            split.append(lineEnd);   
            try {   
                // 发送图片数据    
                output.writeBytes(split.toString());   
                output.write(file.getData(), 0, file.getData().length);   
                output.writeBytes(lineEnd);   
            } catch (IOException e) {   
                throw new RuntimeException(e);   
            }   
        }   
    }   
       
    /*  
     * 构建表单字段内容,格式请参考HTTP 协议格式(用FireBug可以抓取到相关数据)。(以便上传表单相对应的参数值)  
     * 格式如下所示:  
     * --****************fD4fH3hK7aI6  
     * Content-Disposition: form-data; name="action"  
     * // 一空行,必须有  
     * upload  
     */   
    private void addFormField(Set<Map.Entry<Object,Object>> params, DataOutputStream output) {   
        StringBuilder sb = new StringBuilder();   
        for(Map.Entry<Object, Object> param : params) {   
            sb.append(twoHyphens + boundary + lineEnd);   
            sb.append("Content-Disposition: form-data; name=\"" + param.getKey() + "\"" + lineEnd);   
            sb.append(lineEnd);   
            sb.append(param.getValue() + lineEnd);   
        }   
        try {   
            output.writeBytes(sb.toString());// 发送表单字段数据    
        } catch (IOException e) {   
            throw new RuntimeException(e);   
        }   
    }   
       
    /**  
     * 直接通过 HTTP 协议提交数据到服务器,实现表单提交功能。  
     * @param actionUrl 上传路径  
     * @param params 请求参数key为参数名,value为参数值  
     * @param files 上传文件信息  
     * @return 返回请求结果  
     */   
    public String post(String actionUrl, Set<Map.Entry<Object,Object>> params, Image[] files) {   
        HttpURLConnection conn = null;   
        DataOutputStream output = null;   
        BufferedReader input = null;   
        try {   
            URL url = new URL(actionUrl);   
            conn = (HttpURLConnection) url.openConnection();   
            conn.setConnectTimeout(120000);   
            conn.setDoInput(true);        // 允许输入    
            conn.setDoOutput(true);        // 允许输出    
            conn.setUseCaches(false);    // 不使用Cache    
            conn.setRequestMethod("POST");   
            conn.setRequestProperty("Connection", "keep-alive");   
            conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary);   
               
            conn.connect();   
            output = new DataOutputStream(conn.getOutputStream());   
               
            addImageContent(files, output);    // 添加图片内容    
               
            addFormField(params, output);    // 添加表单字段内容    
               
            output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 数据结束标志    
            output.flush();   
               
            int code = conn.getResponseCode();   
            if(code != 200) {   
                throw new RuntimeException("请求‘" + actionUrl +"’失败!");   
            }   
               
            input = new BufferedReader(new InputStreamReader(conn.getInputStream()));   
            StringBuilder response = new StringBuilder();   
            String oneLine;   
            while((oneLine = input.readLine()) != null) {   
                response.append(oneLine + lineEnd);   
            }   
               
            return response.toString();   
        } catch (IOException e) {   
            throw new RuntimeException(e);   
        } finally {   
            // 统一释放资源    
            try {   
                if(output != null) {   
                    output.close();   
                }   
                if(input != null) {   
                    input.close();   
                }   
            } catch (IOException e) {   
                throw new RuntimeException(e);   
            }   
               
            if(conn != null) {   
                conn.disconnect();   
            }   
        }   
    }   
       
    public static void main(String[] args) {   
        try {   
            String response = "";   
               
            BufferedReader in = new BufferedReader(new FileReader("config/actionUrl.properties"));   
            String actionUrl = in.readLine();   
               
            // 读取表单对应的字段名称及其值    
            Properties formDataParams = new Properties();   
            formDataParams.load(new FileInputStream(new File("config/formDataParams.properties")));   
            Set<Map.Entry<Object,Object>> params = formDataParams.entrySet();   
               
            // 读取图片所对应的表单字段名称及图片路径    
            Properties imageParams = new Properties();   
            imageParams.load(new FileInputStream(new File("config/imageParams.properties")));   
            Set<Map.Entry<Object,Object>> images = imageParams.entrySet();   
            Image[] files = new Image[images.size()];   
            int i = 0;   
            for(Map.Entry<Object,Object> image : images) {   
                Image file = new Image(image.getValue().toString(), image.getKey().toString());   
                files[i++] = file;   
            }   
//            Image file = new Image("images/apple.jpg", "upload_file");    
//            Image[] files = new Image[0];    
//            files[0] = file;    
               
            response = new UploadImage().post(actionUrl, params, files);   
            System.out.println("返回结果:" + response);   
        } catch (IOException e) {   
            e.printStackTrace();   
        }   
    }   

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/41944.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpPost是HTTP请求方法之一,用于向服务器提交数据。multipart/form-data请求是一种特殊的POST请求,用于上传文件或提交包含多个部分的表单数据。 在multipart/form-data请求中,需要设置Content-Type属性,并指定boundary(分隔符)。这个分隔符用于隔开提交的表单中不同部分的数据或分割多个文件。在设置Content-Type时,必须同时指定使用的boundary,否则上传过程中会出错导致上传不成功。boundary也可以自定义设置。 在Java中,可以使用HttpURLConnection类发送HttpPost multipart/form-data请求。可以通过设置请求头的方式指定Content-Type为multipart/form-data,并设置boundary。例如: urlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); 这样设置之后,就可以使用HttpPost方法发送multipart/form-data请求,将文件或表单数据以多个部分的形式提交给服务器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [HttpHttpURLConnection-POST发送请求multipart/form-data)](https://blog.csdn.net/qq_16957817/article/details/109205773)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值