欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HttpURLConnection实现参数+文件传输

程序员文章站 2024-02-01 23:28:46
首先看一下别人写的非常全的: https://www.cnblogs.com/tenWood/p/8563617.html 以及我用了后依然有乱码,解决参考: https://www.cnblogs.com/cornucopia/p/4498177.html 历程如下:::: 做商汤人脸识别系统,对 ......

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

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上了,有时间可以去看看。