ejemplo - httpurlconnection java example
Obteniendo UnknownLengthHttpInputStream mientras obtengo InputStream de HttpURLConnection en Android (6)
HttpURLConnection.getInputStream () proporciona UnknownLengthHttpInputStream y, debido a este análisis de documentos, se produce una excepción del analizador SAX.
El siguiente es el código
try{
URL url = new URL(uri);
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
InputStream xml = connection.getInputStream();
System.out.println(connection.getResponseCode());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(connection.getInputStream());
doc.getDocumentElement().normalize();
}catch(Exception e){
e.printStackTrace();
}
Cualquiera sabe el motivo de UnknownLengthHttpInputStream. Recibo este error solo en Android y este código funciona perfectamente en Java Project.
Lo siguiente es la excepción de LogCat:
08-08 11:07:40.490: W/System.err(1493): org.xml.sax.SAXParseException: Unexpected end of document
08-08 11:07:40.504: W/System.err(1493): at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:129)
08-08 11:07:40.510: W/System.err(1493): at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:107)
08-08 11:07:40.510: W/System.err(1493): at com.example.testws.MainActivity.onCreate(MainActivity.java:59)
08-08 11:07:40.520: W/System.err(1493): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-08 11:07:40.530: W/System.err(1493): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
Gracias por adelantado.
¿Has intentado usar las librerías de apache para esto? Sugeriría lo siguiente:
try {
HttpClient client = new DefaultHttpClient();
String getURL = "http://www.google.com";
HttpGet get = new HttpGet(getURL);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
//do something with the response
Log.i("GET RESPONSE",EntityUtils.toString(resEntityGet));
}
} catch (Exception e) {
e.printStackTrace();
}
y luego obtener la secuencia de la HttpEntity
. Algo así como
InputStream st = entity.getContent();
Más ejemplos aquí: http://www.softwarepassion.com/android-series-get-post-and-multipart-post-requests/
Aquí el problema surge cuando el analizador SAX no pudo obtener la longitud de los datos de InputStream
. Para solucionar este problema, guarde los contenidos leídos del xml
( InputStream
) en una variable de cadena y haga un InputStream
de la variable para el método de parse
de DocumentBuilder
. Para ello modifica tu código de la siguiente manera:
try {
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
InputStream xml = connection.getInputStream();
DataInputStream dis = new DataInputStream(xml);
StringBuilder sb = new StringBuilder();
int asci = dis.read();
while (asci > 0) {
sb.append((char) asci);
asci = dis.read();
}
String inputXML = sb.toString();
String predefinedXML = "<?xml version=/"1.0/" encoding=/"UTF-8/"?> <EmotionDB></EmotionDB>";
InputStream inputStream = new ByteArrayInputStream(inputXML.getBytes());//use predefinedXML.getBytes() instead of inputXML.getBytes() for sample test
System.out.println(connection.getResponseCode());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(inputStream);
doc.getDocumentElement().normalize();
} catch (Exception e) {
e.printStackTrace();
}
Aquí el inputStream
tendrá una longitud de contenido correcta, ya que se construye a partir de un ByteArrayInputStream
con un número fijo de bytes.
Deberá cerrar la secuencia de salida correctamente dentro del servicio para evitar esta excepción. Si está utilizando una biblioteca de terceros, asegúrese de haber configurado el encabezado de respuesta
Content-Type
Content-Length
Si está utilizando un servicio java, puede obtener la longitud del contenido del método
File.length()
Es probable que se trate de un servidor Http 1.0 (servidor antiguo o configuración errónea) o que no se mantenga vivo configurado. En este caso, la longitud del flujo se conoce en el momento en que se cierra la conexión desde el servidor. Intente especificar http1.1 y keep-alive en el encabezado de su solicitud (algunas búsquedas en Google lo ayudarán). Solo si el atributo de longitud del contenido se especifica en la respuesta del servidor, sabrá de antemano la longitud del flujo.
Solución alternativa: lea la secuencia http en un ByteBufferStream
completamente (hasta que read()
devuelva -1
). Luego, lance el ByteBufferInputStream a su biblioteca (la longitud se conoce ahora)
Para manejar la respuesta utiliza este método, ¡se encargará de todo!
public static ResponseHandler<String> getResponseHandlerInstance(final Handler handler) {
final ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
public String handleResponse(final HttpResponse response) {
Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
StatusLine status = response.getStatusLine();
Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusCode - " + status.getStatusCode());
Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusReasonPhrase - " + status.getReasonPhrase());
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
try {
result = HTTPRequestHelper.inputStreamToString(entity.getContent());
bundle.putString("RESPONSE", result);
message.setData(bundle);
handler.sendMessage(message);
} catch (IOException e) {
Log.e(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG, e);
bundle.putString("RESPONSE", "Error - " + e.getMessage());
message.setData(bundle);
handler.sendMessage(message);
}
} else {
Log.w(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " empty response entity, HTTP error occurred");
bundle.putString("RESPONSE", "Error - " + response.getStatusLine().getReasonPhrase());
message.setData(bundle);
handler.sendMessage(message);
}
return result;
}
};
return responseHandler;
}
private static String inputStreamToString(final InputStream stream) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "/n");
}
br.close();
return sb.toString();
}
Una vez probarlo así
if(connection.getResponseCode() ==HttpURLConnection.HTTP_OK){
InputStream xml = connection.getInputStream();
..........
}else{
//problem in URI/connection .....
}