PDA

Ver la Versión Completa : [ CONSULTA ] Problema envío archivos a servidor


alfredo89aob
12/07/13, 17:27:25
Estoy haciendo una aplicación cuya función es la de envíar archivos grandes a
un servidor que usa PHP.

Con ficheros pequeños funciona perfectamente, pero al intentar enviar ficheros
grandes, me aparece la siguiente excepción:

07-12 15:11:55.214: E/AndroidRuntime(13818): java.lang.OutOfMemoryError
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.ByteArrayOutputStream.expand(ByteArrayOutp utStream.java:91)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.ByteArrayOutputStream.write(ByteArrayOutpu tStream.java:216)
07-12 15:11:55.214: E/AndroidRuntime(13818): at org.apache.harmony.luni.internal.net.www.protocol. http.RetryableOutputStream.write(RetryableOutputSt ream.java:60)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.DataOutputStream.write(DataOutputStream.ja va:99)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores.doFileUp load(ServicioLogsErrores.java:188)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores.access$0 (ServicioLogsErrores.java:138)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores$1.run(Se rvicioLogsErrores.java:131)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.util.Timer$TimerImpl.run(Timer.java:284)


El código que realiza la subida es:


private void doFileUpload() {

HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String existingFileName = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/audioPrueba.mp3";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
String responseFromServer = "";
String urlString = "http://XXX/upload.php";

try {

// ------------------ CLIENT REQUEST
FileInputStream fileInputStream = new FileInputStream(new File(
existingFileName));
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ existingFileName + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {

dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

}

// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
Log.e("Debug", "File is written");
fileInputStream.close();
dos.flush();
dos.close();

} catch (MalformedURLException ex) {
Log.e("Debug", "error: " + ex.getMessage(), ex);
} catch (IOException ioe) {
Log.e("Debug", "error: " + ioe.getMessage(), ioe);
}

// ------------------ read the SERVER RESPONSE
try {

inStream = new DataInputStream(conn.getInputStream());
String str;

while ((str = inStream.readLine()) != null) {

Log.e("Debug", "Server Response " + str);

}

inStream.close();

} catch (IOException ioex) {
Log.e("Debug", "error: " + ioex.getMessage(), ioex);
}
}


Supongo, que la solución es dividir el fichero de alguna manera, y enviarlo por
partes. Si alguien pudiera echarme una mano sobre como hacer esto, o alguna
otra alternativa que solucione el problema, le estaría muy agradecido.


Gracias,

Un saludo

Arasthel
15/07/13, 12:43:29
Lo único que se me ocurre es que se lea una cantidad más pequeña que la que tienes puesta varias veces hasta que se llegue al final y que esos datos se manden cada vez como bytes en base 64 con el "número de paquete" que tiene y que luego el server PHP se encargue de ensamblarlos según le llegan. Bastante más complicado, pero bueno.

Como ejemplo: StackOverflow (http://stackoverflow.com/a/9987451)

Un saludo.

Carlosdelachica
15/07/13, 17:07:23
Estoy haciendo una aplicación cuya función es la de envíar archivos grandes a
un servidor que usa PHP.

Con ficheros pequeños funciona perfectamente, pero al intentar enviar ficheros
grandes, me aparece la siguiente excepción:

07-12 15:11:55.214: E/AndroidRuntime(13818): java.lang.OutOfMemoryError
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.ByteArrayOutputStream.expand(ByteArrayOutp utStream.java:91)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.ByteArrayOutputStream.write(ByteArrayOutpu tStream.java:216)
07-12 15:11:55.214: E/AndroidRuntime(13818): at org.apache.harmony.luni.internal.net.www.protocol. http.RetryableOutputStream.write(RetryableOutputSt ream.java:60)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.io.DataOutputStream.write(DataOutputStream.ja va:99)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores.doFileUp load(ServicioLogsErrores.java:188)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores.access$0 (ServicioLogsErrores.java:138)
07-12 15:11:55.214: E/AndroidRuntime(13818): at com.example.tweetnews.ServicioLogsErrores$1.run(Se rvicioLogsErrores.java:131)
07-12 15:11:55.214: E/AndroidRuntime(13818): at java.util.Timer$TimerImpl.run(Timer.java:284)


El código que realiza la subida es:


private void doFileUpload() {

HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String existingFileName = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/audioPrueba.mp3";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
String responseFromServer = "";
String urlString = "http://XXX/upload.php";

try {

// ------------------ CLIENT REQUEST
FileInputStream fileInputStream = new FileInputStream(new File(
existingFileName));
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ existingFileName + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {

dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

}

// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
Log.e("Debug", "File is written");
fileInputStream.close();
dos.flush();
dos.close();

} catch (MalformedURLException ex) {
Log.e("Debug", "error: " + ex.getMessage(), ex);
} catch (IOException ioe) {
Log.e("Debug", "error: " + ioe.getMessage(), ioe);
}

// ------------------ read the SERVER RESPONSE
try {

inStream = new DataInputStream(conn.getInputStream());
String str;

while ((str = inStream.readLine()) != null) {

Log.e("Debug", "Server Response " + str);

}

inStream.close();

} catch (IOException ioex) {
Log.e("Debug", "error: " + ioex.getMessage(), ioex);
}
}


Supongo, que la solución es dividir el fichero de alguna manera, y enviarlo por
partes. Si alguien pudiera echarme una mano sobre como hacer esto, o alguna
otra alternativa que solucione el problema, le estaría muy agradecido.


Gracias,

Un saludo

Aparte de lo que ya te han comentado, también deberias de introducir la parte de tu código que descarga/sube de internet en un AsyncTask, ya que si no bloqueas el hilo de ejecución principal.

http://developer.android.com/reference/android/os/AsyncTask.html

(Supongo que no lo haces, aunque como no pones todo el código quizás me equivoque )