zoukankan      html  css  js  c++  java
  • Http multipart/form-data多参数Post方式上传数据

    最近,工作中遇到需要使用java实现http发送get、post请求,简单的之前经常用到,但是这次遇到了上传文件的情况,之前也没深入了解过上传文件的实现,这次才知道通过post接口也可以,是否还有其他方式我还不知道。

    下面来说具体问题,就是要通过接口post方式上传一个excel文件,另外还有其他2个参数,当然,对我来说就是这个文件不知道怎么传,后来通过网上的几篇文章了解到整个文件可以做为一个参数,通过chrome或抓包工具可以看到参数情况如下所示:

    --(boundary的任意字符串)**********
    Content-Disposition: form-data; name="postKey"
    
    postValue
    --(boundary的任意字符串)**********
    Content-Disposition: form-data; name="postKey"; filename="file.getName()"
    Content-Type: image/png; charset=utf-8
    (文件的二进制数据)
    --(boundary的任意字符串)**********--

    这个是引用网上那篇文章的,注意这里只有2个参数,第一个是普通参数,参数名师postKey,参数值是postValue。第二个参数则是要上传的文件,此处是一张图片,当然也可以是txt,excel都可以。这是chrome开发者工具中查看到的样子,注意这个(文件的二进制数据),在chrome里是看不到的,fiddler可以看到是一堆乱码,也就是说把文件转换成二进制字符串了。然后运行了一下,发现还是报错,报400错误,其实这应该指的还是参数格式不对,也就是我拼的这个参数的串格式还是有问题,但此时,我却猜测可能是https的问题,因为我需要调用的接口是https的,之前也是一直在搞http的,没有弄过https的,所以又是一番研究https,并且还得支持上传文件和多参数。后来,按照网上文章的说法引用了几个支持https的类,觉得应该https没问题了,但还是报400错误,于是猜测问题肯定出在字符串的格式上,最后,发现connection.SetRequestProperty时,设置的边界字符串与实际拼参数是的边界有差异,多了两个中划线,去掉后就post成功了,然后又回过头来看到底和https有没有关系,注释掉了所有关于https的代码,发现一样可以post成功,也就是说,至少我这接口虽然是要求https的,但java实现时可以不用考虑https,http就可以。下面贴出代码,注释掉的部分就是与https相关的

        public static ResponseVo importForBatchAddDetailsPost(String requestUrl,String promoId,String operator, String filePath) {
            File file=new File(filePath);
            ResponseVo result = new ResponseVo();
            JSONObject json = new JSONObject();
            String BOUNDARY = "------WebKitFormBoundaryAl9CIOBJ1jfQWTl8";
            URL url;
    
            try {
                url = new URL(requestUrl);
                //SSLContext sc=SSLContext.getInstance("SSL");
                //sc.init(null,new TrustManager[] {new MyX509TrustManager()},new java.security.SecureRandom());
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                //urlConnection.setSSLSocketFactory(sc.getSocketFactory());
                //urlConnection.setHostnameVerifier(new TrustAnyHostnameVerifier());
                urlConnection.setUseCaches(false);
                urlConnection.setRequestMethod("POST");
                urlConnection.setDoOutput(true);
                urlConnection.setDoInput(true);
                urlConnection.setRequestProperty("Connection","Keep-Alive");
                urlConnection.setRequestProperty("Uuser-Agent","Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36");
                urlConnection.setRequestProperty("Charset","UTF-8");
                urlConnection.setRequestProperty("Content-Type","multipart/form-data; boundary=" + "----WebKitFormBoundaryAl9CIOBJ1jfQWTl8");
                urlConnection.connect();
                StringBuilder contentBody1 = new StringBuilder();
                StringBuilder contentBody2 = new StringBuilder();
                String boundary = BOUNDARY+ "
    ";
                DataOutputStream out =new DataOutputStream(urlConnection.getOutputStream());
                byte[] end_data=("------WebKitFormBoundaryAl9CIOBJ1jfQWTl8--".getBytes());
                if (file != null) {
                    //第一部分参数:excel文件
                    contentBody1.append(boundary);
                    contentBody1.append("Content-Disposition: form-data; name="file"; filename="ActImportHouseTemplate.xlsx""+"
    ");
                    contentBody1.append("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"+"
    ");
                    contentBody1.append("
    ");
    
                    out.write(contentBody1.toString().getBytes());
                    //读取excel文件
                    DataInputStream dis = new DataInputStream(new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[(int) file.length()];
                    bytes = dis.read(bufferOut);
                    out.write(bufferOut, 0, bytes);
                    out.write("
    ".getBytes());
                    dis.close();
                    //第二部分参数:其他参数promoId,operator
                    contentBody2.append(boundary);
                    contentBody2.append("Content-Disposition: form-data; name="promoId""+ "
    ");
                    contentBody2.append("
    ");
                    contentBody2.append(promoId+ "
    ");
                    contentBody2.append(boundary);
                    contentBody2.append("Content-Disposition: form-data; name="operator""+ "
    ");
                    contentBody2.append("
    ");
                    contentBody2.append(operator+ "
    ");
    
                    out.write(contentBody2.toString().getBytes());
                    out.write(end_data);
                    out.flush();
    
                    //从服务器获得回答的内容
                    InputStream inputStream=urlConnection.getInputStream();
                    InputStreamReader reader=new InputStreamReader(inputStream);
                    BufferedReader in=new BufferedReader(reader);
                    String strLine = "";
                    String strResponse = "";
                    while ((strLine = in.readLine()) != null) {
                        strResponse += strLine + "
    ";
                        json = JSON.parseObject(strResponse);
                    }
                        result.setJson(json);
                        out.close();
    
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //catch (NoSuchAlgorithmException e){}
            //catch (NoSuchProviderException e){}
            //catch (KeyManagementException e){}
            return result;
        }

    另外贴出https需要用到的两个类

    public class MyX509TrustManager implements X509TrustManager{
    
        public MyX509TrustManager(){}
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    
        public static SSLSocketFactory getSSFactory() throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException{
            TrustManager[] tm = { new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            return  ssf;
        }
    
    }
    public class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session){
            return true;
        }
    }

    具体这两个类是否好使,为什么这么写,我也不确定,如果只是简单post一个https接口,可以参照下面这个文章:https://www.cnblogs.com/lichmama/p/6780298.html   其中用到的bing图片地址已经过期,可以用这个接口查找:https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1,最后拼出来的图片地址如:https://cn.bing.com/az/hprichbg/rb/ComicFans_ZH-CN10352835982_1920x1080.jpg

    综上,总结如下:

    1、java实现的http请求可以有很多种,除了常见的get、post,还可以上传文件

    2、上传文件除了通过接口上传,应该还有其他方式

    3、java实现http和https请求应该大多数是通用的

    4、http上传文件,一定要注意参数字符串的拼接格式,主要有以下几点:

       (1)边界的字符串是随机生成的,只要保证每个边界一样即可,注意只有最后一行边界是在末尾多出两个中划线的

       (2)参数中的换行应该与抓包中的一致,据说是由严格要求,我也没试过不一致的情况

       (3)参数的顺序是否无关紧要,这个我也没试过

    最后贴出两篇参考文章的地址:

    java实现https请求
    https://www.cnblogs.com/lichmama/p/6780298.html
    Http multipart/form-data多参数Post方式上传数据
    https://blog.csdn.net/futianjie_china/article/details/53523814

  • 相关阅读:
    linq to entity之字符串比较
    linq to entity 分页方法不支持LastOrDefault等操作的处理办法
    easyui蛋疼之二 tabs与accordion
    根据下拉框生成控件列表
    第一个flash AS代码
    250多个Jquery各式各样的插件
    对用户控件的访问方式重写
    WP7之Slider绑定textblock设置字体大小
    辉南三角龙湾
    回到正轨
  • 原文地址:https://www.cnblogs.com/techfans/p/9335276.html
Copyright © 2011-2022 走看看