java downloads files to the local tool class by specifying the URL address (including https digital signature request)

java downloads files to the local tool class by specifying the URL address (including https digital signature request)
XFileUtils
public class XFileUtils {<!-- -->

    /**
     * Download files from network Url
     * @param urlStr url path
     * @throwsIOException
     */
    public static String downLoadByUrl(String urlStr,String savePath, String fileName) {<!-- -->
        if (StrUtil.isBlank(fileName)) {<!-- -->
            fileName = getFileName(urlStr);
        }
        InputStream inputStream = null;
        FileOutputStream fos = null;
        try {<!-- -->
            URL url = new URL(urlStr);
            // Prevent https from being reported an error by certificate verification and trust all certificates
            if(urlStr.contains("https")){<!-- -->
                SslUtils.ignoreSsl();
            }
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //Set the timeout to 10 seconds
            conn.setConnectTimeout(10 * 1000);
            //Get the input stream
            inputStream = conn.getInputStream();
            //Get own array
            byte[] getData = readInputStream(inputStream);
            //file save location
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {<!-- --> // Create the file if it does not exist
                saveDir.mkdir();
            }
            File file = new File(saveDir + File.separator + fileName);
            fos = new FileOutputStream(file);
            fos.write(getData);

        } catch (Exception e) {<!-- -->
            e.printStackTrace();
        } finally {<!-- -->
            IoUtil.close(fos);
            IoUtil.close(inputStream);
        }
        return fileName;
    }

    /**
     * Get the byte array from the input stream
     * @param inputStream
     * @return
     * @throwsIOException
     */
    private static byte[] readInputStream(InputStream inputStream) throws IOException {<!-- -->
        byte[] buffer = new byte[4*1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {<!-- -->
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    /**
     * Get the file name from the src file path
     * @param srcRealPath src file path
     * @return file name
     */
    private static String getFileName(String srcRealPath){<!-- -->
        return StringUtils.substringAfterLast(srcRealPath,"/");
    }
}

Test class:

public static void main(String[] args) {<!-- -->
        String url = "https://xxxxxxxxxxxx/kpfw/fpjfzz/v1/exportDzfpwjEwm?Wjgs=PDF & amp;Jym=7D1E & amp;Fphm=23512000000118158368 & amp;Czsj=1699335192593 & amp;Kprq=2023110711 1703";
// String url = "https://www.w3school.com.cn/example/xmle/note.xml";
        String filePath = "D:\workFile";

        String fileName = XFileUtils.downLoadByUrl(url, filePath, null);
    }
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1505)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1420)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:578)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:183)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1665)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:224)
at example.common.utils.XFileUtils.downLoadByUrl(XFileUtils.java:36)
at example.common.utils.XFileUtils.main(XFileUtils.java:89)

From the above test class, we can find that http requests can download files to the local area normally, but if they are https, an error will be reported. This is because Java does not trust the SSL certificate and requires certificate authentication. There are two common solutions to this error.

Solving the error caused by Java’s distrust of SSL certificates (https)
1. Run or package to remove SSL certificate verification (not recommended)

-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true

2. Import the certificate (not recommended)
3. Trust all SSL certificates (recommended)
public class SslUtils {<!-- -->

    private static final Logger logger = LoggerFactory.getLogger(SslUtils.class);
    private static void trustAllHttpsCertificates() throws Exception {<!-- -->
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }
    static class miTM implements TrustManager, X509TrustManager {<!-- -->
        public X509Certificate[] getAcceptedIssuers() {<!-- -->
            return null;
        }
        public boolean isServerTrusted(X509Certificate[] certs) {<!-- -->
            return true;
        }
        public boolean isClientTrusted(X509Certificate[] certs) {<!-- -->
            return true;
        }
        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {<!-- -->
            return;
        }
        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {<!-- -->
            return;
        }
    }
    /**
     * Ignore SSL certificates for HTTPS requests, must be called before openConnection
     * @throwsException
     */
    public static void ignoreSsl() throws Exception{<!-- -->
        HostnameVerifier hv = new HostnameVerifier() {<!-- -->
            public boolean verify(String urlHostName, SSLSession session) {<!-- -->
                logger.info("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
                return true;
            }
        };
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }
}

PS: Must be called before openConnection, SslUtils.ignoreSsl();

At this point, the certificate distrust has been solved through the above tools, and the file can be downloaded normally through the URL address.