2013-09-02 4 views
0

Я пытаюсь сохранить файл из URL с помощью выходного потока. URL-адрес защищен https. Таким образом я получил некоторую ошибку, когда я пытаюсь получить файл в виде следующейКак сохранить файл с HTTPS-url в JAVA?

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(); 
} 

В результате ничего не происходит в выделенном флевере, потому что появляется ошибка. Как я могу получить файл с HTTPS-url?

ответ

8

Соединение HTTPS требует установления связи. То есть явно признают друг друга. Сервер идентифицировал себя сертификатом HTTPS, но вы, видимо, не имеете этого сертификата в своем хранилище доверия, и вы нигде в своем Java-коде явно не подтверждаете идентификацию, поэтому HttpsURLConnection (который используется под обложками здесь) отказывается для продолжения запроса HTTPS.

В качестве примера запуска вы можете использовать следующий код в своем классе, чтобы позволить HttpsURLConnection принимать все SSL-сертификаты независимо от используемого URL-адреса HTTPS.

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); 
    } 
} 

Однако, если вы хотите более детализированное управление на основе каждого сертификата, а затем реализовать методы соответственно как на their Javadoc.


Unrelated к конкретной проблеме, у Вас есть вторая проблема в вашем коде. Вы пытаетесь сохранить загруженный файл как папку, а не как файл.

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

Помимо ошибки синтаксиса, который является более вероятным результатом невнимательности при постановке вопроса (то есть редактирование коды прямо в вопросе вместо фактически copypasting рабочего кода), это не делает никакого смысла. Вы не должны указывать папку как место сохранения. Вы должны указать имя файла. Вы можете при необходимости извлечь его из заголовка 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() вместо этого шаблонного)

+0

Большое вам спасибо за ваш ответ, @BalusC. У меня есть один вопрос о SSL-сертификате. Здесь вы сказали мне, что код примет все SSL-сертификаты. Это означает, что он будет доверять поддельному сертификату или непроверенным сертификатом, не так ли? Еще раз спасибо за ваше дополнительное предложение о дальнейшей проблеме в моем коде. – Takumi

+1

Это правильно. – BalusC

+0

Я хотел бы попросить дополнительную информацию, @BalusC Если я хочу доверять только конкретному сертификату. Не могли бы вы предложить мне, как это сделать? – Takumi

0

Причиной ошибки является то, что Java не может подтвердить действительность сертификата. Это можно устранить, импортировав сертификат в хранилище сертификатов JAVA или «зафиксировав», отключив проверку сертификата SSL.

 Смежные вопросы

  • Нет связанных вопросов^_^