Android HttpURLConnection PUT a Amazon AWS S3 403 error

Subir un archivo a Amazon S3 usando la URL presignada que tiene Firma, Vencimiento y AccessKey, usando el siguiente código Puedo subir el archivo usando código java normal pero el mismo código en Android me da error 403. La URL predeterminada se genera mediante el uso de Amazon SDK

He leído http://developer.android.com/reference/java/net/HttpURLConnection.html y http://android-developers.blogspot.com/2011/09/androids-http-clients.html pero no puedo Averiguar qué parámetro de encabezado debo utilizar, supongo que en android está estableciendo encabezados en la solicitud de que el servidor rechaza

HttpURLConnection connection=(HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("PUT"); OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); out.write("This text uploaded as object."); out.close(); int responseCode = connection.getResponseCode(); 

Excepción: 403; La firma no coincide con: -o

¿Alguien ha encontrado este problema? ¿O más detalles en qué parámetros de cabecera se agregan detrás de escenas de la biblioteca de android?

    5 Solutions collect form web for “Android HttpURLConnection PUT a Amazon AWS S3 403 error”

    Establezca su tipo de contenido de la siguiente manera:

     connection.setRequestProperty("Content-Type"," "); 

    Porque el valor predeterminado para HttpsUrlConnection Genera automáticamente el tipo de contenido como:

     "Content-Type: application/x-www-form-urlencoded" 

    Esto provocará la falta de concordancia entre las firmas.

    Así que después de algún ensayo / error / búsqueda descubrió el problema:

    Si bien la creación de una URL preseleccionada es importante especificar Content-Type (basado en sus datos) o bien seguirá recibiendo 403 Signature no coinciden, el contentType que especifique aquí debe ser mencionado en HttpURLConnection objeto de conexión

      string s3url = s3Client.GetPreSignedURL(new GetPreSignedUrlRequest() .WithBucketName(bucketName) .WithKey(keyName) .WithContentType("application/octet-stream") // IMPORTANT .WithVerb(HttpVerb.PUT) .WithExpires(<YOUR EXPIRATION TIME>); 

    Dentro de su conexión ..add esto al código en cuestión después ("PUT")

      connection.setFixedLengthStreamingMode(< YOUR DATA.LENGTH ?>); connection.setRequestProperty("Content-Type","application/octet-stream"); 

    Compruebe este error , el SDK más reciente debe permitirle establecer Content-Type

    ¿Está utilizando el SDK de AWS para Android ? Que tiene la API correcta y sospecho que será más fácil subir a S3 usando eso, y más seguro para esa materia. Creo que tienen tutoriales, ejemplos de código, y demos allí también.

    También hay una API para S3 y otras clases que pueda necesitar. Un PutObjectRequest es lo que le ayudará a cargar el archivo desde el cliente de teléfono y puede ser útil en su caso.

    La forma de generar la URL:

     private static URL generateRUL(String objectKey, String ACCESS_KEY, String SECRET_KEY, String BUCKET_NAME) { AmazonS3 s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)); URL url = null; try { GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(BUCKET_NAME, objectKey); request.setMethod(com.amazonaws.HttpMethod.PUT); request.setExpiration(new Date( System.currentTimeMillis() + (60 * 60 * 1000))); // Very important ! It won't work without adding this! // And request.addRequestParameter("Content-Type", "application/octet-stream") won't work neither request.setContentType("application/octet-stream"); url = s3Client.generatePresignedUrl(request ); } catch (AmazonServiceException exception) { } catch (AmazonClientException ace) { } return url; } 

    La forma de cargar el archivo:

     public int upload(byte[] fileBytes, URL url) { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("PUT"); connection.setRequestProperty("Content-Type", "application/octet-stream"); // Very important ! It won't work without adding this! OutputStream output = connection.getOutputStream(); InputStream input = new ByteArrayInputStream(fileBytes); byte[] buffer = new byte[4096]; int length; while ((length = input.read(buffer)) > 0) { output.write(buffer, 0, length); } output.flush(); return connection.getResponseCode(); } 

    Yo tuve el mísmo problema. Aquí está la razón por la que lo enfrenté:

    Una URL previamente firmada le da acceso al objeto identificado en la URL, siempre que el creador de la URL previamente firmada tenga permisos para acceder a ese objeto. Es decir, si recibe una URL previamente firmada para cargar un objeto, puede cargarlo únicamente si el creador de la URL previamente firmada tiene los permisos necesarios para cargar ese objeto .

    http://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html

    Una vez que le di mi función lambda permisos PutObject en ese cubo s3, entonces funcionó!

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.