如何在JAVA中保存来自HTTPS网址的文件? [英] How to save the file from HTTPS url in JAVA?

查看:144
本文介绍了如何在JAVA中保存来自HTTPS网址的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to save a file from URL using outputstream. The URL is secure by https. So I got some error when I try to get the file as the following

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打开文件

Suppose that I want to open the file from this 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中没有任何结果,因为错误显示。如何从HTTPS网址获取文件?

The result is nothing happen in the dedicated floder because the error is show up. How can I get the file from the HTTPS url?

推荐答案

HTTPS连接需要握手。即明确地相互承认。服务器已通过HTTPS证书标识自己,但您显然在信任库中没有此证书,并且您在Java代码中没有明确承认标识,因此 HttpsURLConnection (这里正在使用它)拒绝继续HTTPS请求。

A HTTPS connection requires handshaking. I.e. explicitly acknowledge each other. The server has identified itself by a HTTPS certificate, but you apparently don't have this certificate in your trust store and you are nowhere in your Java code explicitly acknowledging the identification, so the HttpsURLConnection (which is being used under the covers here) refuses to continue the HTTPS request.

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

As a kickoff example, you can use the following piece of code in your class to let HttpsURLConnection accept all SSL certificates, regardless of the HTTPS URL you use.

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

If you however want more fine grained control on a per-certificate basis, then implement the methods accordingly as per their Javadoc.

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

Unrelated to the concrete problem, you've a second problem in your code. You're attempting to save it the downloaded file as a folder instead of as a file.

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

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

Apart from the syntax error which is more likely result of carelessness during formulating the question (i.e. editing the code straight in question instead of actually copypasting working code), this isn't making any sense. You should not specify a folder as save location. You should specify a file name. You can if necessary extract it from the Content-Disposition header, or autogenerate one with File#createTempFile(). E.g.

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

(如果你已经使用Java 7,只需使用文件#copy()而不是该样板文件)

(and if you're already on Java 7, just make use of Files#copy() instead of that boilerplate)

这篇关于如何在JAVA中保存来自HTTPS网址的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆