当前位置: 移动技术网 > IT编程>开发语言>Java > HttpURLConnection实现参数+文件传输

HttpURLConnection实现参数+文件传输

2019年08月07日  | 移动技术网IT编程  | 我要评论

蛋包饭怎么做,龙腾海啸txt,点绛唇元好问

首先看一下别人写的非常全的:

https://www.cnblogs.com/tenwood/p/8563617.html

以及我用了后依然有乱码,解决参考:

https://www.cnblogs.com/cornucopia/p/4498177.html

 

历程如下::::

 

做商汤人脸识别系统,对方提供的示例为:

package com.sensetime.bi.senselink.open.api;

import javax.net.ssl.sslexception;
import java.io.*;
import java.net.httpurlconnection;
import java.net.url;
import java.security.messagedigest;
import java.security.nosuchalgorithmexception;
import java.util.hashmap;
import java.util.iterator;
import java.util.map;

public class apidemo {

    //输入你的app_key
    private final static string app_key = "586949450e231c71";
    //输入你的app_secret
    private final static string app_secret = "e27c8593b933fe892969877941d729dd";
    //本机要上传的图片位置
    private final static string path = "f://123.png";
    //要使用的api的uri
    private final static string uri = "/api/v1/recognition/check";

    private final static string boundary = "----webkitformboundarygrbcuhvtenqcbtqn";
    private static string name;

    public static void main(string[] args) throws exception {
        string url = "https://link.bi.sensetime.com" + uri;
        //表单文本参数
        map<string, object> params = new hashmap();
        //表单文件参数
        map<string, byte[]> fileparams = new hashmap();

        file avatar_file = new file(path);
        name = avatar_file.getname();
        long timestamp = gettimestamp();
        //添加表单文本参数
        {
            params.put("app_key", app_key);
            params.put("timestamp", string.valueof(timestamp));
            params.put("sign", getsign(string.valueof(timestamp)));
        }
        //添加表单文件参数
        {
            fileparams.put("face_avatar", getbytes(avatar_file));
        }
        string result = new string(dopost(url, params, fileparams));
        system.out.println(result);

    }

    public static byte[] dopost(string strurl, map<string, object> params, map<string, byte[]> fileparams) throws exception {
        url url = new url(strurl);
        httpurlconnection connection = (httpurlconnection) url.openconnection();
        connection.setdooutput(true);
        connection.setdoinput(true);
        connection.setusecaches(false);
        connection.setinstancefollowredirects(true);
        connection.setrequestmethod("post");
        connection.setrequestproperty("accept", "application/json, text/plain, */*"); // 设置接收数据的格式
        connection.setrequestproperty("content-type", "multipart/form-data; boundary=" + boundary); // 设置发送数据的格式
        connection.connect();
        dataoutputstream out = new dataoutputstream(connection.getoutputstream());
        iterator it = params.entryset().iterator();
        while (it.hasnext()) {
            map.entry<string, string> entry = (map.entry) it.next();
            string key = entry.getkey();
            string value = entry.getvalue();
            out.writebytes("--" + boundary + "\r\n");
            out.writebytes("content-disposition: form-data; name=\"" + key + "\"");
            out.writebytes("\r\n\r\n");
            out.writebytes(value + "\r\n");
        }
        if (fileparams != null && fileparams.size() > 0) {
            iterator fileit = fileparams.entryset().iterator();
            while (fileit.hasnext()) {
                map.entry<string, byte[]> fileentry = (map.entry<string, byte[]>) fileit.next();
                out.writebytes("--" + boundary + "\r\n");
                out.writebytes("content-disposition: form-data; name=\"" + fileentry.getkey()
                        + "\"; filename=\"" + name + "\"");
                out.writebytes("\r\n");
                out.writebytes("content-type: image/jpeg");//此处很关键
                out.writebytes("\r\n\r\n");
                out.write(fileentry.getvalue());
                out.writebytes("\r\n");
            }
        }
        out.writebytes("--" + boundary + "--");
        out.flush();
        out.close();
        inputstream in = null;
        int code = connection.getresponsecode();
        try {
            if (code == 200) {
                in = connection.getinputstream();
            } else {
                in = connection.geterrorstream();
            }
        } catch (sslexception e) {
            e.printstacktrace();
            return new byte[0];
        }
        bytearrayoutputstream baout = new bytearrayoutputstream();
        byte[] buff = new byte[1024];
        int len;
        while ((len = in.read(buff)) != -1) {
            baout.write(buff, 0, len);
        }
        byte[] bytes = baout.tobytearray();
        in.close();
        return bytes;
    }


    public static long gettimestamp() {
        return system.currenttimemillis();
    }
    
    public static string getsign(string timestamp) {
        string code = timestamp + "#" + app_secret;
        return getmd5(code);
    }
    
    private static string getmd5(string sourcestr) {
        string result = "";
        try {
            messagedigest md = messagedigest.getinstance("md5");
            md.update(sourcestr.getbytes());
            byte b[] = md.digest();
            int i;
            stringbuffer buf = new stringbuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(integer.tohexstring(i));
            }
            result = buf.tostring();
        } catch (nosuchalgorithmexception e) {
            system.out.println(e);
        }
        return result;
    }
    
    public static byte[] getbytes(file f) {
        try {
            inputstream in = new fileinputstream(f);
            bytearrayoutputstream out = new bytearrayoutputstream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = in.read(b)) != -1)
                out.write(b, 0, n);
            in.close();
            out.close();
            return out.tobytearray();
        } catch (ioexception e) {
            system.out.println("***请设置文件路径***");
        }
        return null;
    }
}

用起来ok,但中文显示乱码。后来上网找方法,参照这条博文https://www.cnblogs.com/tenwood/p/8563617.html。将out.writebytes(content)替换为out.write(content.getbytes())  。依然乱码。

又参照这条博文解决 https://www.cnblogs.com/cornucopia/p/4498177.html。心里历程如下:

/**
运行后结果对于中文传递过去后是乱码。
            原因:
            out.writebytes();这个方法点进去结构为:
            public final void writebytes(string s) throws ioexception {
                int len = s.length();
                for (int i = 0 ; i < len ; i++) {
                out.write((byte)s.charat(i));
            }
                inccount(len);
            }
            因为java里的char类型是16位的,一个char可以存储一个中文字符,在将其转换为 byte后高8位会丢失,这样就无法将中文字符完整的输出到输出流中。
            所以在可能有中文字符输出的地方最好先将其转换为字节数组,然后再通过write写入流,
            目前尝试过这种方法:把上面链接代码中的out.writebytes(content);替换为out.write(content.getbytes());先把数据转成byte在写入流,执行成功.
            执行成功,但还是乱码,找了很久,后来把out.write(content.getbytes())改为out.write(content.getbytes("utf-8"))解决。
            原因是:
                   在java中,string的getbytes()方法是得到一个操作系统默认的编码格式的字节数组。这表示在不同的操作系统下,返回的东西不一样!
                          把string转换成bytes,各种编码转换成的bytes不同,比如utf-8每个汉字转成3bytes,而gbk转成2bytes,所以要说明编码方式,否则用缺省编码。
                   (另外:与getbytes相对的,可以通过new string(byte[], decode)的方式来还原)
**/

 

最终代码:

public static string dopost(string strurl, map<string, object> params, map<string, byte[]> fileparams,string filename) throws exception {
        logger.info("*******dopost1()参数为:\n strurl:"+strurl +"\n params:"+params +" \n fileparams:"+fileparams+" \n filename:"+filename);
        string ret = null;
        url url = null;
        inputstream in = null;
        string two_hyphens = "--";
        string line_end = "\r\n";
        try {
            url = new url(strurl);
            httpurlconnection connection = (httpurlconnection) url.openconnection();//得到connection对象
            /************************************设置请求头*************************************************/
            connection.setrequestmethod("post");    //设置请求方式为post
            connection.setdooutput(true);           //允许写出
            connection.setdoinput(true);            //允许读入
            connection.setusecaches(false);         //不使用缓存
            connection.setinstancefollowredirects(true);//本次连接是否自动处理重定向(true:系统自动处理重定向;false:则需要自己从http reply中分析新的url)(置所有的http连接是否自动处理重定向:public static void httpurlconnection.setfollowredirects(boolean followredirects))
            connection.setrequestproperty("charset", "utf-8");//编码格式
            connection.setrequestproperty("content-type", "multipart/form-data ; boundary=" + boundary); // 设置发送数据的格式(form-data格式)   //boundary为头部分隔符,头部拼接时需要分隔符。例如下面的有多个"content-disposition"拼接时需要用到此分隔符
            connection.setrequestproperty("accept", "application/json, text/plain, */*");               // 设置接收数据的格式(json格式)
            connection.connect(); //连接
            /************************************输出流,写数据,start*************************************************/
            dataoutputstream out = new dataoutputstream(connection.getoutputstream());//获得输出流对象
            stringbuffer strbufparam = new stringbuffer();
            iterator it = params.entryset().iterator();
            while (it.hasnext()) {
                //封装键值对数据
                map.entry<string, string> entry = (map.entry) it.next();
                string key = entry.getkey();
                string value = entry.getvalue();

                strbufparam.append(two_hyphens);
                strbufparam.append(boundary);
                strbufparam.append(line_end);//"--" + boundary + "\r\n"
                strbufparam.append("content-disposition: form-data; name=\"" + key + "\"");
                strbufparam.append(line_end);
                strbufparam.append(line_end);
                strbufparam.append(value);
                strbufparam.append(line_end);
            }
            out.write(strbufparam.tostring().getbytes("utf-8"));
            strbufparam.tostring().getbytes();
            //写入图片参数
            if (fileparams != null && fileparams.size() > 0) {
                iterator fileit = fileparams.entryset().iterator();
                while (fileit.hasnext()) {
                    map.entry<string, byte[]> fileentry = (map.entry<string, byte []>) fileit.next();
                    //拼接文件的参数
                    stringbuffer strbuffile = new stringbuffer();
                    strbuffile.append(two_hyphens);
                    strbuffile.append(boundary);
                    strbuffile.append(line_end);
                    //strbuffile.append("content-disposition: form-data; name=\"" + "image" + "\"; filename=\"" + file.getname() + "\"");
                    strbuffile.append("content-disposition: form-data; name=\"" + fileentry.getkey() + "\"; filename=\"" + filename + "\"");// fileentry.getkey():文件全路径。filename:文件名称
                    strbuffile.append(line_end);
                    strbuffile.append("content-type: image/jpeg");//此处很关键----文件格式
                    strbuffile.append(line_end);
                    strbuffile.append(line_end);
                    out.write(strbuffile.tostring().getbytes());
                    out.write(fileentry.getvalue());//文件 (此参数之前调用了本页面的重写方法getbytes(file f),将文件转换为字节数组了 )
                    out.write((line_end).getbytes());
                }
            }

            //写入标记结束位
            byte[] enddata = ( two_hyphens + boundary + two_hyphens + line_end).getbytes();//写结束标记位
            out.write(enddata);
            out.flush();
            out.close();
            /*
            下面是商汤提供的示例方法。
            dataoutputstream out = new dataoutputstream(connection.getoutputstream());//获得输出流对象
            iterator it = params.entryset().iterator();
            while (it.hasnext()) {
                //写入键值对数据一
                map.entry<string, string> entry = (map.entry) it.next();
                string key = entry.getkey();
                string value = entry.getvalue();
                out.writebytes("--" + boundary + "\r\n");
                out.writebytes("content-disposition: form-data; name=\"" + key + "\"");
                out.writebytes("\r\n\r\n");
                out.writebytes(value + "\r\n");
            }
            //写入图片参数
            if (fileparams != null && fileparams.size() > 0) {
                iterator fileit = fileparams.entryset().iterator();
                while (fileit.hasnext()) {
                    map.entry<string, byte[]> fileentry = (map.entry<string, byte[]>) fileit.next();
                    out.writebytes("--" + boundary + "\r\n");
                    out.writebytes("content-disposition: form-data; name=\"" + fileentry.getkey() + "\"; filename=\"" + filename + "\"");// fileentry.getkey():文件全路径。filename:文件名称
                    out.writebytes("\r\n");
                    out.writebytes("content-type: image/jpeg");//此处很关键----文件格式
                    out.writebytes("\r\n\r\n");
                    out.write(fileentry.getvalue());//文件
                    out.writebytes("\r\n");
                }
            }
            out.writebytes("--" + boundary + "--");
            out.flush();
            out.close();
             */


            /************************************输出流,写数据完成end*************************************************/
            int code = connection.getresponsecode(); //获得响应码(200为成功返回)
            try {
                if (code == httpurlconnection.http_ok) {
                    in = connection.getinputstream(); //获取响应流
                } else {
                    in = connection.geterrorstream(); //获取响应流
                }
            } catch (sslexception e) {
                e.printstacktrace();
                return "";
            }
            /**********读取返回的输入流信息**************/
            byte[] bytes = null;
            bytearrayoutputstream baout = new bytearrayoutputstream();
            byte[] buff = new byte[1024];
            int len;
            while ((len = in.read(buff)) != -1) {
                baout.write(buff, 0, len);
            }
            bytes = baout.tobytearray();
            in.close();
            ret = new string(bytes) ;
        }catch(exception e){
            logger.error("向商汤服务器发送指令时出错dopost():"+e.getmessage());
            e.printstacktrace();
        }
        return ret;
    }

 /**
     * 将文件转换为byte数组
     * @param f
     * @return
     */
    public static byte[] getbytes(file f) {
        try {
            inputstream in = new fileinputstream(f);
            bytearrayoutputstream out = new bytearrayoutputstream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = in.read(b)) != -1)
                out.write(b, 0, n);
            in.close();
            out.close();
            return out.tobytearray();
        } catch (ioexception e) {
            logger.error("***请设置文件路径***");
            e.printstacktrace();
        }
        return null;
    }

 

 

在 https://www.cnblogs.com/tenwood/p/8563617.html博文下面,作者说封装了方法,放到github上了,有时间可以去看看。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网