Baixar conteudo de uma URL

10 respostas
M

Estou tentando baixar um arquivo via Java (no Android) usando a classe URL. Mas é retornado o seguinte erro quando tento abrir o Stream:

java.io.IOException: SSL handshake failure: Failure in SSL library, usually a protocol error
 error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:604 0xaf076228:0x00000000)
     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
 ...

Meu código para baixar é simplesmente o seguinte:

URL url = new URL(downloadUrl);
            InputStream stream = url.openStream();
            byte[] content = new byte[stream.available()];
            stream.read(content);
            stream.close();

O “downloadUrl” é um link como o seguinte:

https://contentserver.com/d/761/34/215656/5de1a41ea3bc9c81978af95ed19b03286f64d9a3

Se eu abrir esta URL no browser vou conseguir baixar um arquivo, preciso baixa-lo via Java.

Alguma sugestão?

10 Respostas

T

Aqui o erro foi diferente…

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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
	at java.net.URL.openStream(Unknown Source)
	at apresentacao.teste.main(teste.java:17)
Caused by: 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.validator.PKIXValidator.doBuild(Unknown Source)
	at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
	at sun.security.validator.Validator.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	... 14 more
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)
	... 20 more
T

Testa esse trecho de codigo

try {
			String conteudo2 = "http://gregui.wordpress.com";
			url = new URL(conteudo2);
			BufferedReader br = new BufferedReader(
					new InputStreamReader(url.openStream()));

			StringBuffer buffer = new StringBuffer();

			String linha;
			while ((linha = br.readLine()) != null) {
				buffer.append(linha);
			}
			br.close();
			System.out.println(buffer.toString()); 
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
M

É que a URL que passei ali na verdade foi modificada.

E o erro está exatamente em url.openStream(), ou até mesmo url.getContent(), ambos lançam o erro que mencionei. A URL real baixa um arquivo em um formato especifico, o servidor envia este link e não o link para o arquivo direto.

D

A classe URLConnection é implementada no Android?
Se sim, vc tentou usá-la?
Se usou e não funcinou, sua conexão passa por um proxy? Se sim, você tentou fazer autenticação no proxy?

[]'s

M

Sim a URLConnection é implementada no Android.

Eu também tentei abrir a connection e depois pegar o Stream e lança o mesmo erro no getInputStream

URL url = new URL(downloadUrl);
		URLConnection conn = url.openConnection();
		conn.connect();
		InputStream stream = conn.getInputStream();

E não tem nenhum Proxy, tanto que eu consigo usar a mesma rotina para baixar imagens.

Acredito que o problema é por causa do link não apontar para um arquivo direto, acredito que ele apenas jogue na Stream os dados e o browser que os baixa no formato.

D

Então, estranho isso, pq o que diz o tipo do recurso é o content-type não o nome do recurso.
Quando vc baixa imagens é https tbm ou é http?

M

É https também.

Eu dei um wget no link e o eu recebo o seguinte resultado:

marcos@marcos-AY675AA-AC4-s5320br:~$ wget https://www.xeriph.com.br/d/762/36/123510/5de1a41ea3bc9c81188af95fd19a03286f64d9a4
--2011-03-09 17:44:39--  https://www.xeriph.com.br/d/762/36/123510/5de1a41ea3bc9c81188af95fd19a03286f64d9a4
Resolving www.xeriph.com.br... 174.36.220.147
Connecting to www.xeriph.com.br|174.36.220.147|:443... connected.
HTTP request sent, awaiting response... 301 MOVED PERMANENTLY
Location: https://www.xeriph.com.br/d/762/36/123510/5de1a41ea3bc9c81188af95fd19a03286f64d9a4/ [following]
--2011-03-09 17:44:40--  https://www.xeriph.com.br/d/762/36/123510/5de1a41ea3bc9c81188af95fd19a03286f64d9a4/
Reusing existing connection to www.xeriph.com.br:443.
HTTP request sent, awaiting response... 302 FOUND
Location: http://208.43.77.220:8080/fulfillment/URLLink.acsm?action=enterorder&ordersource=Xeriph&orderid=61c305fd0bcf1c74117c87182f8d9032e2c02821&resid=urn%3Auuid%3A0ad80f58-2123-4e0d-a9b6-654b193998c5&gbauthdate=Qua%2C%2009%20Mar%202011%2020%3A44%3A41%20%2B0000&dateval=[telefone removido]&gblver=4&auth=b6fe32521e25a95ce855fb6e90b3780b7fa4de00 [following]
--2011-03-09 17:44:41--  http://208.43.77.220:8080/fulfillment/URLLink.acsm?action=enterorder&ordersource=Xeriph&orderid=61c305fd0bcf1c74117c87182f8d9032e2c02821&resid=urn%3Auuid%3A0ad80f58-2123-4e0d-a9b6-654b193998c5&gbauthdate=Qua%2C%2009%20Mar%202011%2020%3A44%3A41%20%2B0000&dateval=[telefone removido]&gblver=4&auth=b6fe32521e25a95ce855fb6e90b3780b7fa4de00
Connecting to 208.43.77.220:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5358 (5.2K) [application/vnd.adobe.adept+xml]
Saving to: `5de1a41ea3bc9c81188af95fd19a03286f64d9a4'

100%[======================================>] 5,358       34.8K/s   in 0.2s    

2011-03-09 17:44:41 (34.8 KB/s) - `5de1a41ea3bc9c81188af95fd19a03286f64d9a4' saved [5358/5358]

Reparei que ele faz um 301 depois um 302 até chegar no arquivo, a URLConnection trata isso ou preciso fazer algo?

D

Marky, eu acho que isso é responsabilidade do protocolo, não do URLConnection.
Vc pode tentar dar uma pesquisada sobre isso, pq sinceramente, não sei :frowning:

[]'s

M

Acho que vou conseguir resolver isso fazendo as requesições eu mesmo por HttpRequest até chegar no arquivo, vou ver o que consigo.

Anyway… eu li na documentação que o openConnection retorna um HttpsURLConnection se for um protocolo https, e ele redireciona até 5 vezes. Mas não está dando muito certo.

L

Marky, você conseguiu dar uma solução?
Estou com o mesmo problema.

Acesso uma url para autenticação do usuário e na servlet através
response.getWriter().println("");
devolvo uma resposta sobre a autenticação.

O problema é que não consigo receber esse valor. Abaixo o método que estou utilizando.

Ahhhh, esse acesso a url é atraves do android, setei setInstanceFollowRedirects para não permitir o redirecionamento automatico, pois, quando estoura os dados 3G (30mb) do aparelho é redirecionando para o portal da vivo.

O engraçado é que quando a conexão é por WiFi ou por dados 3G onde os mesmos não foram estourados, o rotina roda sem problemas.

private String autenticandoUsuario(String sUrl) {
		HttpURLConnection connection = null;
		try {
			String[] userSenha = new String[2];
			userSenha = daoComun.getUserSenha();

			String urlOri = sUrl+"/autenticacao?AFVUSUARIO=" + userSenha[0]+"&AFVSENHA=" + userSenha[1];

			URL url = new URL(urlOri);
			connection = (HttpURLConnection) url.openConnection();
			connection.setInstanceFollowRedirects(false);
			HttpURLConnection.setFollowRedirects(false);
			connection.setReadTimeout(10000); 
			connection.setConnectTimeout(30000);
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			connection.setDoInput(true);  
			connection.setDoOutput(false);  
			connection.setUseCaches(false);  
			connection.setRequestMethod("GET");
			connection.connect();

			int responseCode = connection.getResponseCode();
			System.out.println("responseCode "+responseCode);
			String location = connection.getHeaderField("Location");
			System.out.println("location "+location);

			InputStream is = connection.getInputStream();
			int ch;
			StringBuffer sb =new StringBuffer();
			while((ch = is.read()) != -1){
				sb.append( (char)ch );
			}
			is.close();
			System.out.println("Resposta: "+sb.toString());

			return sb.toString();
		} catch (Throwable e) {
			e.printStackTrace();
			ExceptionAFV.setMsgErro(e, cxt, false);
			return "ERRO";
		} finally {
			if (connection != null)
				connection.disconnect();
		}
	}

At.

Criado 9 de março de 2011
Ultima resposta 25 de nov. de 2014
Respostas 10
Participantes 4