zoukankan      html  css  js  c++  java
  • Android模拟 HTTP multipart/formdata 请求协议信息实现图片上传

    问题:
    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();   
            }   
        }   
  • 相关阅读:
    chrome浏览器中安装以及使用Elasticsearch head 插件
    windows10 升级并安装配置 jmeter5.3
    linux下部署Elasticsearch6.8.1版本的集群
    【Rollo的Python之路】Python 爬虫系统学习 (八) logging模块的使用
    【Rollo的Python之路】Python 爬虫系统学习 (七) Scrapy初识
    【Rollo的Python之路】Python 爬虫系统学习 (六) Selenium 模拟登录
    【Rollo的Python之路】Python 爬虫系统学习 (五) Selenium
    【Rollo的Python之路】Python 爬虫系统学习 (四) XPath学习
    【Rollo的Python之路】Python 爬虫系统学习 (三)
    【Rollo的Python之路】Python sys argv[] 函数用法笔记
  • 原文地址:https://www.cnblogs.com/top5/p/2408014.html
Copyright © 2011-2022 走看看