Tengo muy poca idea de cómo funciona el código html.Lo que quiero hacer es exactamente similar a la siguiente pero en android

HTML:

<body>
    <form action="<%= some_url %>" method="post" enctype="multipart/form-data">
        <input type="file" name="myFile">
        <input type="submit" value="Submit">
    </form>
</body>

He probado el siguiente código

private static void postToUrl(String url_to_upload_on,
        String file_name_with_ext, byte[] byteArray) {

    String attachmentName = "file";
    String attachmentFileName = file_name_with_ext;
    String crlf = "\r\n";
    String twoHyphens = "--";
    String boundary =  "*****";

    try{

    URL url = new URL(url_to_upload_on);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");

    connection.setRequestProperty(
        "Content-Type", "multipart/form-data;boundary=" + boundary);
    DataOutputStream request = new DataOutputStream(
            connection.getOutputStream()); 
    request.writeBytes(twoHyphens + boundary + crlf);
    request.writeBytes("Content-Disposition: form-data; name=\"" +
        attachmentName + "\";filename=\"" + 
        attachmentFileName + "\"" + crlf);
    request.writeBytes(crlf);
    request.write(byteArray);
    request.writeBytes(crlf);
    request.writeBytes(twoHyphens + boundary + 
        twoHyphens + crlf);
    request.flush();
    request.close();

    }catch(Exception e){
        e.printStackTrace();
    }


}

esto me da ningún error pero cuando tengo un error-flujo con-

 Log.w(TAG, "connection.getErrorStream() = " +      connection.getErrorStream());

me sale esto-

12-14 18:25:54.911: W/uploadToBlobStore(30558): httpUrlConnection.getErrorStream() = com.android.okhttp.internal.http.[email protected]

sin éxito.

PS – estoy subiendo un archivo a google blobstore

PS – no la puedo usar Apache http bibliotecas o de sus varias partes de la clase como android dice su depreciado

EDITAR 1

Ahora estoy usando el siguiente código, pero se está trabajando sólo para archivos de menos de 2.3 Mb –

private static void postToUrl3(String url_to_upload_on,
        String file_name_with_ext, byte[] byteArray, String mimeType) {

    CloseableHttpClient httpClient = null;

    try {

        httpClient = HttpClientBuilder.create().build();

        HttpPost postRequest = new HttpPost(url_to_upload_on);


        MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
        reqEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);            
        ByteArrayBody bab = new ByteArrayBody(byteArray, file_name_with_ext);           
        reqEntity.addPart("file", bab);         
        postRequest.setEntity(reqEntity.build());


        httpClient.execute(postRequest);//takes time

    } catch (Exception e) {
        Log.w("uploadToBlobStore", "postToUrl Exception e = " + e);
        e.printStackTrace();
    } finally {
        if (httpClient != null) {
            Log.w("uploadToBlobStore", "connection.closing ");
            try {
                httpClient.close();
            } catch (IOException e) {
                Log.w("uploadToBlobStore", "connection.closing errot e = "
                        + e);
                e.printStackTrace();
            }
        }
    }
}

cómo hacer que funcione con archivos de gran tamaño?

PS- lo estoy enviando a blobstore y me puso la maxUploadSizeBytesy MaxUploadSizeBytesPerBlob a 30MB.Yo no soy capaz de averiguar el problema con el tamaño, ya que google blobstore documentación dice –

Google App Engine incluye la Blobstore servicio, que permite que las aplicaciones para la publicación de datos de objetos limitado sólo por la cantidad de datos que puede ser cargado o descargado a través de una única conexión HTTP.

Así que puede ser un problema con la conexión de http? y si es así, ¿cómo puedo configurarlo.

4 Comentarios

  1. 70

    Estoy usando HttpURLConnection para lograr esto.

    Crear un Multipart clase personalizada ::

    public class MultipartUtility {
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    private String charset;
    private OutputStream outputStream;
    private PrintWriter writer;
    /**
    * This constructor initializes a new HTTP POST request with content type
    * is set to multipart/form-data
    *
    * @param requestURL
    * @param charset
    * @throws IOException
    */
    public MultipartUtility(String requestURL, String charset)
    throws IOException {
    this.charset = charset;
    //creates a unique boundary based on time stamp
    boundary = "===" + System.currentTimeMillis() + "===";
    URL url = new URL(requestURL);
    httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setUseCaches(false);
    httpConn.setDoOutput(true);    //indicates POST method
    httpConn.setDoInput(true);
    httpConn.setRequestProperty("Content-Type",
    "multipart/form-data; boundary=" + boundary);
    outputStream = httpConn.getOutputStream();
    writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
    true);
    }
    /**
    * Adds a form field to the request
    *
    * @param name  field name
    * @param value field value
    */
    public void addFormField(String name, String value) {
    writer.append("--" + boundary).append(LINE_FEED);
    writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
    .append(LINE_FEED);
    writer.append("Content-Type: text/plain; charset=" + charset).append(
    LINE_FEED);
    writer.append(LINE_FEED);
    writer.append(value).append(LINE_FEED);
    writer.flush();
    }
    /**
    * Adds a upload file section to the request
    *
    * @param fieldName  name attribute in <input type="file" name="..." />
    * @param uploadFile a File to be uploaded
    * @throws IOException
    */
    public void addFilePart(String fieldName, File uploadFile)
    throws IOException {
    String fileName = uploadFile.getName();
    writer.append("--" + boundary).append(LINE_FEED);
    writer.append(
    "Content-Disposition: form-data; name=\"" + fieldName
    + "\"; filename=\"" + fileName + "\"")
    .append(LINE_FEED);
    writer.append(
    "Content-Type: "
    + URLConnection.guessContentTypeFromName(fileName))
    .append(LINE_FEED);
    writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
    writer.append(LINE_FEED);
    writer.flush();
    FileInputStream inputStream = new FileInputStream(uploadFile);
    byte[] buffer = new byte[4096];
    int bytesRead = -1;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
    }
    outputStream.flush();
    inputStream.close();
    writer.append(LINE_FEED);
    writer.flush();
    }
    /**
    * Adds a header field to the request.
    *
    * @param name  - name of the header field
    * @param value - value of the header field
    */
    public void addHeaderField(String name, String value) {
    writer.append(name + ": " + value).append(LINE_FEED);
    writer.flush();
    }
    /**
    * Completes the request and receives response from the server.
    *
    * @return a list of Strings as response in case the server returned
    * status OK, otherwise an exception is thrown.
    * @throws IOException
    */
    public List<String> finish() throws IOException {
    List<String> response = new ArrayList<String>();
    writer.append(LINE_FEED).flush();
    writer.append("--" + boundary + "--").append(LINE_FEED);
    writer.close();
    //checks server's status code first
    int status = httpConn.getResponseCode();
    if (status == HttpURLConnection.HTTP_OK) {
    BufferedReader reader = new BufferedReader(new InputStreamReader(
    httpConn.getInputStream()));
    String line = null;
    while ((line = reader.readLine()) != null) {
    response.add(line);
    }
    reader.close();
    httpConn.disconnect();
    } else {
    throw new IOException("Server returned non-OK status: " + status);
    }
    return response;
    }
    }

    Uso de ella (async manera) ::

        MultipartUtility multipart = new MultipartUtility(requestURL, charset);
    //In your case you are not adding form data so ignore this
    /*This is to add parameter values */
    for (int i = 0; i < myFormDataArray.size(); i++) {
    multipart.addFormField(myFormDataArray.get(i).getParamName(),
    myFormDataArray.get(i).getParamValue());
    }
    //add your file here.
    /*This is to add file content*/
    for (int i = 0; i < myFileArray.size(); i++) {
    multipart.addFilePart(myFileArray.getParamName(),
    new File(myFileArray.getFileName()));
    }
    List<String> response = multipart.finish();
    Debug.e(TAG, "SERVER REPLIED:");
    for (String line : response) {
    Debug.e(TAG, "Upload Files Response:::" + line);
    //get your server response here.
    responseString = line;
    }
    • Muchas gracias por compartir esto. Me ha dado un montón de búsqueda para encontrar una alternativa a org.apache.http.entity.mime.MultipartEntity y el código funciona de maravilla. 🙂
    • Bienvenido @ban-geoingeniería
    • Sólo he encontrado un problema con este código. El addFormField método es añadir un salto de línea para el valor real que se envía al servidor. Para hacer que funcione como está previsto, se me han quitado el final .append(LINE_FEED) de ese método. Saludos,
    • …Me encontré con problemas con ese fix (el servidor de tirar un error 400). La mejor solución parece ser la de sustituir writer.append(value).append(LINE_FEED); writer.flush(); con writer.append(value); writer.flush(); writer.append(LINE_FEED);
    • Cuál debe ser el valor de «juego de caracteres»?
    • debe ser el conjunto de caracteres como UTF-8,UTF-16 sea cual sea su necesidad.
    • Gracias, Tu respuesta realmente útil
    • gracias, tu respuesta fue muy útil..
    • es bueno saber que la respuesta es útil para usted.
    • ¿Cómo conseguir el getParamName() método? ¿Usted tiene que escribir su propio getter?
    • sí . usted puede crear sus propias clases personalizadas para establecer y obtener valor de la clave que desea pasar. @AkilanArasu
    • Gracias, tu respuesta fue muy útil.
    • Su ignorando «\n» en addFormField. Cuando el envío de un texto que contiene «\n» su sustitución «\n» con un espacio. Por favor, hágamelo saber cuál es el problema.
    • el === en la frontera de la creación de un error en golang.(pánico: mime: no válido medios de parámetro). He tenido que cambiar a — para resolver el problema
    • Tuve que comentar dos LINE_FEED en el acabado() método para que este código funcione.
    • Acaba de cambiar el límite === para cualquier otra cosa, como: ***** y funciona perfectamente.
    • Muchas gracias bro he perdido todo el día…………..Muchas gracias bro por sus valiosos comentarios…gracias otra vez…..+100
    • Muchas gracias! Pero los encabezados de no trabajo (que deben establecerse como un httpConn.setRequestProperty en el constructor), y los códigos de respuesta > 400 no funcionan bien (porque las de dar un httpConn.getErrorStream(), no httpConn.getInputStream()).

  2. 8

    uso okhttp y uso de la siguiente fragmento de código (tomado de recetas)

    ajustar los valores de encabezado de acuerdo a lo que su servidor de espera.

    private static final String IMGUR_CLIENT_ID = "...";
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    private final OkHttpClient client = new OkHttpClient();
    public void run() throws Exception {
    //Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
    RequestBody requestBody = new MultipartBuilder()
    .type(MultipartBuilder.FORM)
    .addPart(
    Headers.of("Content-Disposition", "form-data; name=\"title\""),
    RequestBody.create(null, "Square Logo"))
    .addPart(
    Headers.of("Content-Disposition", "form-data; name=\"image\""),
    RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
    .build();
    Request request = new Request.Builder()
    .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
    .url("https://api.imgur.com/3/image")
    .post(requestBody)
    .build();
    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    System.out.println(response.body().string());
    }
    • lo siento por la respuesta tardía.¿Tengo que añadir que este ‘okHttp’ como una biblioteca externa?
    • ok he añadido okHttp el uso de la jarra. pero eclipse me da el error «error en El tipo de okio.ByteString no puede ser resuelto. Es indirectamente se hace referencia de lo requerido .de archivos de clases» en ‘RequestBody.crear(MEDIA_TYPE_PNG, nuevo Archivo (el»sitio web/static/logotipo-cuadrado.png»)))’
    • Le sugiero que utilice Android Studio.. si es absolutamente necesario utilizar eclipse sin embargo, la descarga de la okio jar (github.com/square/okio) y agregar de la misma forma agregó okhttp
    • sí, no uso Eclipse, ha sido suspendida por el SDK de Android. Usted no necesita añadir ningún frascos manualmente en Android Studio, sólo tiene que escribir una línea en su gradle archivo. Uso okhttp con la modernización de hacer las llamadas mucho más simple. plaza.github.io/retrofit plaza.github.io/okhttp
    • GRACIAS! Este código no es la mejor solución, pero el puntero a okhttp es! Sólo quiero destacar a nadie luchando contra este problema de la carga de un archivo de Android que okhttp (actualmente okhttp3) es el camino a seguir! Cuando empecé en esto y vi okhttp mencionó que fue cuidado, porque uno está siempre reacios a utilizar una biblioteca libre que nunca has oído hablar. Sin embargo, después de haber sido forzado a esta solución, no puedo recomendar okhttp demasiado alto. Parece tener un fuerte registro de mantenimiento, es fácil de usar e instalar (en AndroidStudio), y resuelve un problema que otros métodos no (para mí).
    • Para la corriente y limpia soluciones con okhttp de diciembre de 2016, consulte stackoverflow.com/questions/23512547/…
    • href=»https://twitter.com/JakeWharton/status/482563299511250944″ >internamente android ha sido el uso de okhttp desde el 4,4 por eso recomiendo el uso de it

  3. 5

    Como alternativa, puede utilizar Retrofit.

    Puede especificar una llamada como esta:

    @Multipart
    @POST("/user/photo")
    Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

    a continuación, crear algo como esto:

    Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .build();
    GitHubService service = retrofit.create(GitHubService.class);

    y finalmente ejecutarlo como este:

    service.updateUser(Photo, description).enqueue() –> asincrónica

    service.updateUser(Photo, description).execute() –> sincrónico

    Consulte la documentación aquí

  4. -1

    Volea es una buena librería de http para varias partes de los datos.
    AndroidMultiPartEntity clase es para el progreso de escucha.

        public class AndroidMultiPartEntity extends MultipartEntity
    {
    private final ProgressListener listener;
    public AndroidMultiPartEntity(final ProgressListener listener) {
    super();
    this.listener = listener;
    }
    public AndroidMultiPartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
    super(mode);
    this.listener = listener;
    }
    public AndroidMultiPartEntity(HttpMultipartMode mode, final String boundary,
    final Charset charset, final ProgressListener listener) {
    super(mode, boundary, charset);
    this.listener = listener;
    }
    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
    super.writeTo(new CountingOutputStream(outstream, this.listener));
    }
    public static interface ProgressListener {
    void transferred(long num);
    }
    public static class CountingOutputStream extends FilterOutputStream {
    private final ProgressListener listener;
    private long transferred;
    public CountingOutputStream(final OutputStream out,
    final ProgressListener listener) {
    super(out);
    this.listener = listener;
    this.transferred = 0;
    }
    public void write(byte[] b, int off, int len) throws IOException {
    out.write(b, off, len);
    this.transferred += len;
    this.listener.transferred(this.transferred);
    }
    public void write(int b) throws IOException {
    out.write(b);
    this.transferred++;
    this.listener.transferred(this.transferred);
    }
    }
    }
    Call the Async task like this
    new UploadFileToServer().execute();
    The Call method:
    private class UploadFileToServer extends AsyncTask<Void, Integer, String> {
    @Override
    protected void onPreExecute() {
    super.onPreExecute();
    }
    @Override
    protected void onProgressUpdate(Integer... progress) {
    }
    @Override
    protected String doInBackground(Void... params) {
    return uploadFile();
    }
    private String uploadFile() {
    String responseString = null;
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(Config.Seeker_Image_Upload);
    try {
    AndroidMultiPartEntity entity = new AndroidMultiPartEntity(new AndroidMultiPartEntity.ProgressListener() {
    @Override
    public void transferred(long num) {
    publishProgress((int) ((num / (float) totalSize) * 100));
    }
    });
    File sourceFile = new File(Path);
    //Adding file data to http body
    entity.addPart("logo", new FileBody(sourceFile));
    //Extra parameters if you want to pass to server
    //entity.addPart("website", new StringBody("www.androidhive.info"));
    //String emailaddress = UserActivity.emailaddress;
    /*preferences = SeekerProfile.this.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    email_address = preferences.getString("EMAILADDRESS", "");*/
    entity.addPart("EMAILADDRESS", new StringBody(email_address));
    entity.addPart("OPER", new StringBody(Operation_recruiter_logo_upload));
    totalSize = entity.getContentLength();
    httppost.setEntity(entity);
    //Making server call
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity r_entity = response.getEntity();
    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode == 200) {
    //Server response
    responseString = EntityUtils.toString(r_entity);
    } else {
    responseString = "Error occurred! Http Status Code: " + statusCode;
    }
    } catch (ClientProtocolException e) {
    responseString = e.toString();
    } catch (IOException e) {
    responseString = e.toString();
    }
    return responseString;
    }
    @Override
    protected void onPostExecute(String result) {
    //Log.e(TAG, "Response from server: " + result);
    enter code here
    }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here