HttpUrlConnection.getInputStream() 400 异常的问题

写在前面:首先,网上90%的解决方法是在使用getInputStream()之前先getResponseCode()获取状态码进行判断:如果出错,就用getErrorStream();不出错就用getInputStream()。不得不说这种方法脑洞真奇怪。我们要做的是从根源解决问题,而不是主动对问题视而不见。既然你getInputStream()出错了,返回的状态码不对,你就应该去从根本解决问题啊,是400就找400引发的根源,是404就去看链接是不是写的不对,是500就去程序里debug哪里出错了;换了个getErrorStream()去获取数据,要么获取到的是空的,要么就是对应的状态码数据,比如400,那就是bad request,404,那就是not found。获取这个有啥用呢?只有极少数的解决方法是从getInputStream()的源码去分析问题,另外的极少数是从状态码的根源去着手。
我的问题如下图:
HttpUrlConnection.getInputStream() 400 异常的问题_第1张图片

在这里插入图片描述

部分代码如下:

 if (params.getEndpoint().startsWith("http")) {
                if (params.getEndpoint().startsWith("https")) {
                    url = new URL("https", host, 80,
                        "/" + params.getBucket() + "/" + key + imageParams);
                } else {
                    url = new URL("http", host, 80,
                        "/" + params.getBucket() + "/" + key + imageParams);
                }
            }

            conn = (HttpURLConnection) url.openConnection();
            conn.setUseCaches(false);
            conn.setDoInput(true);
            conn.setRequestMethod("GET");
            conn.connect();
            int code = conn.getResponseCode();
            inputStream = conn.getInputStream();

同一个方法,不同的key,得到了不同的状态码。开始还以为是不同的接口里的具体处理方式不同,可能是因为URL长度导致的400错误。后来重新用了几个参数才发现不是这样,并且两个URL链接放在浏览器里面是可以访问的(图中debug时URL的值)。这个问题困扰了我好久,直到我把链接从浏览器复制下来,大概长这样

.........(前面的省略)picUri=devpictures/2020110911/E%E5%AE%9E%E6%96%BD2.0%E6%B5%8B%E8%AF%95%E8%BD%A6%E5%9C%BA/20201109112729.995_plateinfo_17511111181123.%E6%97%A0%E7%89%8C.full.jpg&compressFlag=1

可以很清楚得看到,链接里面的中文汉字都被转换成形如了E%E5%AE%9E%E6%96%这种形式。恍然大悟的我才明白是那个相对较长的链接里有中文字符未处理,果断把代码从之前的改成了下面的形式

 url = new URL("https", host, 80, "/" + params.getBucket() + "/" + key + imageParams);
url = new URL("https", host, 80,"/" + params.getBucket() + "/" + URLEncoder.encode(key, "utf-8") + imageParams);

问题完美解决!

注:URLEncoderencode()方法会将链接的所有特殊字符转换成特定的编码(比如utf-8)。用的时候注意不要把不必要转换的字符一并转了,比如http://里的://也属于特殊字符。

你可能感兴趣的:(java,http,后端)