如何在JAVA中保存来自HTTPSurl的文件?

我正在尝试使用outputstream从URL保存文件。 该URL由https保护。 所以当我尝试获取以下文件时出现了一些错误

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source) at java.net.URL.openStream(Unknown Source) Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) at java.security.cert.CertPathBuilder.build(Unknown Source) ... 60 more 

假设我想从这个URL打开文件

 https://www.filepicker.io/api/file/KW9EJhYtS6y48Whm2S6D?signature=4098f262b9dba23e4766ce127353aaf4f37fde0fd726d164d944e031fd862c18&policy=eyJoYW5kbGUiOiJLVzlFSmhZdFM2eTQ4V2htMlM2RCIsImV4cGlyeSI6MTUwODE0MTUwNH0= 

所以我做了类似的事情:

 try{ URL URL = new URL('https://www.filepicker.io/api/file/KW9EJhYtS6y48Whm2S6D?signature=4098f262b9dba23e4766ce127353aaf4f37fde0fd726d164d944e031fd862c18&policy=eyJoYW5kbGUiOiJLVzlFSmhZdFM2eTQ4V2htMlM2RCIsImV4cGlyeSI6MTUwODE0MTUwNH0='); String = path = "D://download/"; InputStream ins = url.openStream(); OutputStream ous = new FileOutputStream(path); final byte[] b = new byte[2048]; int length; while ((length = inputStream.read(b)) != -1) { ous.write(b, 0, length); } ins.close(); ous.close(); } 

结果是在专用floder中没有发生任何事情,因为错误显示出来。 如何从HTTPSurl获取文件?

HTTPS连接需要握手。 即明确承认彼此。 服务器已通过HTTPS证书识别自己,但您显然在信任库中没有此证书,并且您在Java代码中没有明确承认该标识,因此HttpsURLConnection (在此处使用的内容)拒绝继续HTTPS请求。

作为启动示例,您可以使用类中的以下代码来让HttpsURLConnection接受所有SSL证书,无论您使用何种HTTPS URL。

 static { final TrustManager[] trustAllCertificates = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; // Not relevant. } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } } }; try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCertificates, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (GeneralSecurityException e) { throw new ExceptionInInitializerError(e); } } 

但是,如果您希望在每个证书的基础上进行更细粒度的控制,则根据其Javadoc相应地实现这些方法。


具体问题无关 ,您的代码中存在第二个问题。 您试图将下载的文件另存为文件夹而不是文件。

 String = path = "D://download/"; OutputStream ous = new FileOutputStream(path); 

除了语法错误之外,更有可能是在制定问题时粗心大意(即直接编辑代码而不是实际复制工作代码),这没有任何意义。 您不应将文件夹指定为保存位置。 您应该指定文件名。 您可以根据需要从Content-Disposition标头中提取它,或者使用File#createTempFile()自动生成它。 例如

 File file = File.createTempFile("test-", ".jpg", new File("D:/download/")); Files.copy(url.openStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); 

(如果你已经在Java 7上,只需使用Files#copy()而不是那个样板文件)

导致错误的原因是Java无法确认证书的有效性。 这可以通过将证书导入JAVA证书存储来修复,或通过禁用SSL证书validation来“修复”。

Interesting Posts