Télécharger une liste d'array à l'aide de httpurlconnection multipart / form-data

11

J'ai besoin de télécharger Arraylistdes images sur le serveur sans utiliser de bibliothèque. J'utilise Asynctaskpour télécharger une seule image et cela fonctionne parfaitement avec l'aide de httpurlconnection multipart / form-data. Maintenant, je dois changer mon code pour télécharger plusieurs fichiers de tout type en utilisant, Arraylist<String>mais mon problème est que le code existant FileinputStreamne prend pas en charge la liste d'array et je ne sais pas quoi utiliser au lieu de Fileinputstreamtélécharger la liste d'arrayl vers le serveur et je ne le fais pas souhaitez utiliser n'importe quelle bibliothèque pour cela non plus.

public class multipart_test extends AsyncTask<Void,Void,String> {
    Context context;
    String Images;
    public static final String TAG = "###Image Uploading###";


    public multipart_test(Context context,String Upload_Images) {
        this.context = context;
        this.Images = Upload_Images;

    }

    @Override
    protected String doInBackground(Void... params) {
        BufferedReader reader;
        String WebPath = null;
        try {
            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary = "*****";
            int bytesRead, bytesAvailable, bufferSize;
            byte[] buffer;
            int maxBufferSize = 1024 * 1024;
            //todo change URL as per client ( MOST IMPORTANT )
            URL url = new URL("10.0.0.1/uploadMultipart.php");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // Allow Inputs &amp; Outputs.
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            // Set HTTP method to POST.
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            FileInputStream fileInputStream;
            DataOutputStream outputStream;
            outputStream = new DataOutputStream(connection.getOutputStream());
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);

            outputStream.writeBytes("Content-Disposition: form-data; name=\"reference\""+ lineEnd);
            outputStream.writeBytes(lineEnd);
            //outputStream.writeBytes("my_refrence_text");
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);

            outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadFile\";filename=\"" + "profileImage" +"\"" + lineEnd);
            outputStream.writeBytes(lineEnd);

            //Dummy ArrayList for upload
            ArrayList<String> uploadFiles = new ArrayList<>();
            uploadFiles.add(Images);
            uploadFiles.add(Images);
            uploadFiles.add(Images);
            uploadFiles.add(Images);


            fileInputStream = new FileInputStream(uploadFiles); // NOT SUPPORTING ARRAYLIST HERE
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            buffer = new byte[bufferSize];

            // Read file
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);

            while (bytesRead > 0) {
                outputStream.write(buffer, 0, bufferSize);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
                fileInputStream.close();
            }
            // Responses from the server (code and message)
            int serverResponseCode = connection.getResponseCode();
            String result = null;
            if (serverResponseCode == 200) {
                StringBuilder s_buffer = new StringBuilder();
                InputStream is = new BufferedInputStream(connection.getInputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String inputLine;
                while ((inputLine = br.readLine()) != null) {
                    s_buffer.append(inputLine);
                }
                result = s_buffer.toString();
            }
            connection.getInputStream().close();
            outputStream.flush();
            outputStream.close();
            if (result != null) {
                Log.d("result_for upload", result);
            }
            return WebPath;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


}

J'ai également essayé de mettre FileInputStreamen boucle, mais le téléchargement d'images en plusieurs demandes n'est pas ce que je veux. Mon serveur requiert l'application pour faire une seule demande pour n nombre d'images. Toute aide serait appréciée mais sans utiliser de bibliothèque

Ritu
la source
Les classes Http sont obsolètes, utilisez la modification ou une autre bibliothèque
Jaiprakash Soni
vous pouvez utiliser la modification et télécharger plusieurs images en une seule demande
Priyankagb

Réponses:

4

REMARQUE que je n'ai pas essayé si ce code fonctionne effectivement avec HttpURLConnection mais il devrait.

D'après ce que j'ai lu sur Internet, vous pouvez toujours utiliser la boucle que vous avez mentionnée, mais avec quelques modifications.

J'ai suivi le didacticiel sur les parties multiples / les données de formulaire ici dev.to , pour en faire plus un poste d'apprentissage, je vais vous dire quelle est cette méthode qui devrait se produire.

Le multipart / form-data est envoyé comme ceci

--boundary
Content-Disposition: form-data; name="something1"

data1
--boundary
Content-Disposition: form-data; name="something2"

data2
--boundary--

Ce que je ferais, c'est de créer une nouvelle méthode mais vous pouvez simplement écrire le code dans votre méthode déjà existante.

public byte[] get_multipart_data(List<String> files, String boundary)

Vous voulez écrire est la frontière suivie de la disposition puis des données . Faites cela pour tous les fichiers, puis vous envoyez la limite de fermeture . Cela générera la structure multipart / form-data que vous souhaitez.

En psudo-code, ce serait

loop for all files
    write "--boundary"
    write "Content-Disposition: ...."
    write image_data
end
write "--boundary--"

Le code pourrait être écrit comme ceci, d'abord vous définissez vos variables

ByteArrayOutputStream message = null;
DataOutputStream stream = null;

FileInputStream fileInputStream;

int maxBufferSize = 1024 * 1024;
byte[] buffer = new byte[maxBufferSize];
byte[] sendData = new byte[0];

Voici où les données seront générées. Il commence par concaténer la frontière puis lire les données. Ces données sont écrites dans le flux et vous continuez la boucle pour tous les fichiers / images.

try {
    message = new ByteArrayOutputStream();
    stream = new DataOutputStream(message);

    // Loop though all file names
    for(String fileName : files) {
        stream.writeBytes("--" + boundary + "\r\n"); // Start boundary
        stream.writeBytes("Content-Disposition: form-data; name=\"" + fileName + "\"\r\n\r\n");

        // Read the image data
        fileInputStream = new FileInputStream(fileName);
        int readBytes = 0;
        while((readBytes = fileInputStream.read(buffer)) != -1) {
            // Write file data to output
            stream.write(buffer, 0, readBytes);
        }
        fileInputStream.close();

        stream.writeBytes("\r\n");
    }
    stream.writeBytes("--" + boundary + "--\r\n"); // Closing boundary

    sendData = message.toByteArray();
} catch(IOException e) {
    e.printStackTrace();
}

Maintenant, le tableau d'octets sendDatacontiendra les données multipart / form que vous devez envoyer avec votre HttpURLConnection.

Je ne suis pas si actif ici depuis longtemps. Dites-moi si vous avez besoin de plus de spécifications ou que je clarifie mon texte: D

HardCoded
la source
Si je lance une boucle, je dois faire plusieurs demandes de téléchargement de tableau. J'ai besoin de télécharger un tableau sur le serveur en un seul appel.
Ritu
D'après ce que je comprends, vous voulez envoyer n images au serveur en un seul appel HttpURLConnection. Vous pouvez essayer d'utiliser un format zip où vous saisissez les fichiers avec ZipEntry, sinon ce que j'ai écrit ne sera toujours qu'une seule demande. @Ritu
HardCoded
Est-il possible pour vous d'utiliser une boucle en dehors de votre asynctask? Par exemple, si vous avez 3 fichiers à télécharger, vous exécutez 3 asynctask indépendamment. De cette manière, si un problème ou un problème est détecté pour une image (processus de téléchargement), d'autres images (processus) continuent à être téléchargées. compter par un compteur dans votre classe et garder un délai (temps estimé) si besoin (pour alerter pour l'existence d'un problème lors du téléchargement).
maniaq
1
@maniaq ce n'est pas du code optimal pour exécuter plusieurs asynctask pour la même tâche. Nous devons éviter les appels réseau partout où nous le pouvons.
androidXP
0

FileinputStream ne prend pas en charge ArrayList. Mais il existe un moyen de contourner le problème en utilisant ObjectOutputStream . Il sérialisera également votre ArrayList. Vérifiez les modifications dans le code.

       //Changes required in your code
        ArrayList<String> uploadFiles = new ArrayList<>();
        uploadFiles.add(Images);
        uploadFiles.add(Images);
        uploadFiles.add(Images);
        uploadFiles.add(Images);

        fileInputStream = new FileInputStream("listImages"); 
        java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(fileInputStream); 
        oos.writeObject(uploadFiles);

        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, maxBufferSize);
        buffer = new byte[bufferSize];
        ...
        ...
        ...
        oos.close();

Happy Coding :)

Attiq ur Rehman
la source
0

Je ne sais pas si l'utilisation d'une seule tâche asynchrone est un must pour vous.

Comme vous l'avez dit, votre code fonctionne parfaitement pour une seule image. Donc, pour télécharger plusieurs fichiers depuis arraylist, vous devez simplement modifier un peu votre AsyncTask. Téléchargez simplement un fichier après l'autre Ou si vous ne voulez même pas faire autant de modifications, déclarez simplement la variable globale contenant l'index de l'élément en cours de téléchargement et dans OnPostExecute, créez une nouvelle instance de la tâche asynchrone et passez l'élément suivant dans la liste. J'espère que c'est clair.

mayank1513
la source