2017-09-01 2 views
0

J'essaye de télécharger un fichier sur le S3 d'Amazon en utilisant une URL pré-signée. Je reçois l'URL d'un serveur qui génère l'URL & me l'envoie dans le cadre d'un objet JSON. Je reçois l'URL comme une chaîne, quelque chose comme ceci:Importer un fichier dans l'URL pré-signée AWS S3 à l'aide de Retrofit2

https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/ImageName?X-Amz-Security-Token=xxfooxx%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Fxxbarxx%3D&X-Amz-Algorithm=xxAlgoxx&X-Amz-Date=20170831T090152Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=xxcredxx&X-Amz-Signature=xxsignxx

Malheureusement, quand je passe à ce Retrofit2, il modifie la chaîne en essayant de le faire dans une URL. J'ai mis encoding=true qui s'est occupé de la plupart du problème mais pas complètement. Je sais que la chaîne fonctionne comme elle est. Je l'ai essayé dans le facteur & obtenir une réponse positive.

1er J'ai essayé juste de mettre la chaîne (à l'exception de ce que je coupe comme baseUrl) dans son ensemble dans le chemin

public interface UpdateImageInterface { 
    @PUT("{url}") 
    Call<Void> updateImage(@Path(value="url", encoded=true) String url, Body RequestBody image); 
} 

Le code d'appel:

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/") 
      .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is "ImageName..." 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

Cela fonctionne la plupart du temps, sauf la la '?' (après "ImageName") est converti en "% 3F". Cela provoque une demande incorrecte/400.

Ma tentative suivante a été de créer une requête avec Retrofit2, puis de vider la chaîne entière (avec plusieurs requêtes) dans la requête.

public interface UpdateImageInterface { 
    @PUT("ImageName") 
    Call<Void> updateProfilePhoto(@Query(value="X-Amz-Security-Token", encoded = true) String token, @Body RequestBody image); 
} 

Le code d'appel:

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/") 
      .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is "xxfooxx..." 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

Cela devient le '?' rendu correctement mais tous les « & » se changer à « % 26 »

Enfin j'ai essayé passer toute la chaîne dans baseUrl() mais qui donne un IllegalArgumentException pour ne pas avoir «/» à la fin.

Je sais que je pourrais analyser l'URL pré-signée pour faire plusieurs requêtes & les assembler dans Retrofit2 comme des requêtes devraient être faites mais je voudrais éviter ce traitement.

Pour reformuler la question:

est-il un moyen facilement (sans lourd parsing String) télécharger un fichier à S3 avec une URL pré-signé en utilisant Retrofit2? Avec l'aide d'un collègue, c'est la solution.

+0

La bibliothèque, ou quelque chose dont elle dépend, semble un peu cassée. Jetez un oeil aux commentaires, ici: https: //github.com/square/retrofit/issues/1199 ... notez le dernier, en particulier. –

+0

@ Michael-sqlbot Oui cela ressemble au même problème. J'ai trouvé une solution (peut-être plus d'un travail autour?). Je posterai quand j'aurai un peu de temps dans quelques jours. – Gary99

Répondre

1

public interface UpdateImageInterface { 
    @PUT 
    Call<Void> updateImage(@Url String url, @Body RequestBody image); 
} 

Indicatif téléphonique:

/* since the pre-signed URL from S3 contains a host, this dummy URL will 
    * be replaced completely by the pre-signed URL. (I'm using baseURl(String) here 
    * but see baseUrl(okhttp3.HttpUrl) in Javadoc for how base URLs are handled 
    */ 
    Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl("http://www.dummy.com/") 
     .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is the String as received from AWS S3 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

Javadoc pour plus d'informations sur @Url (classe Url) & baseUrl() (classe Retrofit.Builder)

0

Utilisez les éléments suivants lors du téléchargement directement à S3 en utilisant URL presigned .

@Multipart 
@PUT 
@Headers("x-amz-acl:public-read") 
Call<Void> uploadFile(@Url String url, @Header("Content-Type") String contentType, @Part MultipartBody.Part part);