2017-06-20 2 views
0

J'ai un serveur en amont qui accepte les soumissions d'images en utilisant le repos. L'image présentée est une partie d'une charge utile JSON similaire à celuiTransfert en continu d'une image en base64 en utilisant le rétro-éclairage

{ 
    "name": "Blah.jpg", 
    "uploader": "user1", 
    "image": "<base64.....>" 
} 

En utilisant cette stratégie fonctionne pour les petites images, mais génère des erreurs de mémoire sur les images plus grandes.

Est-il possible de diffuser le composant base64 de l'image? Passer quelque chose comme un itérateur qui sera utilisé pour lire des morceaux de l'image, les base64 et les envoyer directement au réseau?

+1

Serait-il possible de télécharger des fichiers directement en utilisant 'POST' sans encapsuler les blobs dans les charges JSON? –

+2

Pensez à utiliser tus pour envoyer une image, il est conçu pour cela et il permet de reprendre les transferts interrompus. Votre solution actuelle est en fait la pire possible, notez que la chaîne base64 est environ 1,5 fois plus grande que votre image source. Vous devez télécharger l'image avec tus et fournir tus upload id dans votre json – user1209216

+0

Merci pour les commentaires. Nous envisageons de demander à notre amont de repenser l'API et nous permettre de publier directement comme @LyubomyrShaydariv dit. La raison de l'image base64 incorporée était de faire un seul appel HTTP pour passer les métadonnées de l'image et de l'image. Nous aurons probablement à faire 2 appels dans la nouvelle API. – Lmwangi

Répondre

0

Je résolu cela avec ce qui suit, dans une classe qui étend okhttp3.RequestBody:

private void writeFile(File file, BufferedSink sink) throws IOException { 
    byte buf[] = new byte[3000]; 
    try (FileInputStream fin = new FileInputStream(file)) { 
     while (fin.read(buf) >= 0) { 
      byte encoded[] = Base64.encodeBase64(buf); 
      sink.write(encoded); 
     } 
    } 
} 

Il utilise Android de android.util.Base64 Apache Commons' org.apache.commons.codec.binary.Base64 pour coder un morceau en mémoire tampon des données. J'ai fini par écrire les autres champs json séparément, avec suffisamment de granularité pour pouvoir insérer l'enregistrement de fichier exactement là où j'en avais besoin.

EDIT:

Comme vous pouvez le voir dans mes modifications ci-dessus, j'ai fini par passer à Apache commons-codec, via compile 'commons-codec:commons-codec:1.5' dans mon dossier build.gradle.

Je n'ai pas eu le temps d'étudier pourquoi la solution Android SDK ne fonctionnait pas. J'ai essayé leur Base64.encode(buf, Base64.NO_WRAP) comme suggéré ailleurs - soi-disant équivalent à Apache Commons 'encodeBase64(byte[]) - mais cela n'a pas fonctionné, d'où le commutateur. Le problème aurait pu être sur notre backend, alors n'excluez pas la solution Android SDK basée sur mon post seul - Je voulais juste ajouter cette note afin que les lecteurs puissent voir l'extrait de code qui a finalement fonctionné pour moi .

1

Pas avec Gson ou Moshi. Ces deux bibliothèques nécessitent que les chaînes soient en mémoire avant de les émettre dans un flux.