Laden Sie die Arrayliste mit httpurlconnection multipart / form-data hoch


11

Ich muss ArraylistBilder auf den Server hochladen , ohne eine Bibliothek zu verwenden. Ich verwende Asynctaskzum Hochladen eines einzelnen Bildes und es funktioniert perfekt mit Hilfe von httpurlconnection Multipart / Formulardaten. Jetzt muss ich meinen Code ändern, um mehrere Dateien eines beliebigen Typs mithilfe von hochzuladen, Arraylist<String>aber mein Problem ist, dass die vorhandenen Codes FileinputStreamkeine Arraylist unterstützen und ich keine Ahnung habe, was ich verwenden soll, anstatt FileinputstreamArraylist auf den Server hochzuladen, und ich nicht Ich möchte auch dafür eine beliebige Bibliothek verwenden.

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;
    }


}

Ich habe auch versucht, eine FileInputStreamSchleife zu erstellen, aber das Hochladen von Bildern in mehrere Anfragen ist nicht das, was ich will. Die App meines Servers erfordert eine einzelne Anforderung für n Anzahl von Bildern. Jede Hilfe wäre dankbar, aber ohne Verwendung einer Bibliothek


HTTP-Klassen sind veraltet, verwenden Sie eine Nachrüstung oder eine andere Bibliothek
Jaiprakash Soni

Sie können Nachrüsten verwenden und mehrere Bilder in einer einzigen Anfrage hochladen
Priyankagb

Antworten:


4

HINWEIS, dass ich nicht versucht habe, ob dieser Code tatsächlich mit der HttpURLConnection funktioniert, aber es sollte.

Nach dem, was ich aus dem Internet gelesen habe, können Sie die erwähnte Schleife immer noch verwenden, jedoch mit einigen Änderungen.

Ich habe das Tutorial zu mehrteiligen / Formulardaten hier dev.to befolgt , um dies mehr zu einem Lernbeitrag zu machen. Ich werde Ihnen sagen, was mit dieser Methode passieren soll.

Die mehrteiligen / Formulardaten werden so gesendet

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

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

data2
--boundary--

Ich würde eine neue Methode erstellen, aber Sie können den Code einfach in Ihre bereits vorhandene Methode schreiben.

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

Sie möchten schreiben, ist die Grenze, gefolgt von der Disposition und dann den Daten . Tun Sie das für alle Dateien und senden Sie dann die schließende Grenze . Dadurch wird die gewünschte mehrteilige / Formulardatenstruktur generiert .

Im Psudo-Code wäre dies

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

Der Code könnte so geschrieben werden, zuerst definieren Sie Ihre Variablen

ByteArrayOutputStream message = null;
DataOutputStream stream = null;

FileInputStream fileInputStream;

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

Hier werden die Daten generiert. Es beginnt mit der Verkettung der Grenze und dem anschließenden Lesen der Daten. Diese Daten werden in den Stream geschrieben und Sie setzen die Schleife für alle Dateien / Bilder fort.

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();
}

Jetzt enthält das Byte-Array sendDatadie mehrteiligen / Formulardaten , die Sie mit Ihrer HttpURLConnection senden müssen.

Ich war hier schon lange nicht mehr so ​​aktiv. Sagen Sie mir, wenn Sie weitere Spezifikationen benötigen oder wenn ich meinen Text klarstelle: D.


Wenn ich eine Schleife ausführe, muss ich mehrere Anfragen zum Hochladen von Arrays stellen. Ich muss ein Array in einem einzigen Aufruf auf den Server hochladen.
Ritu

Ich verstehe, dass Sie n Bilder in einem einzigen HttpURLConnection-Aufruf an den Server senden möchten. Sie können versuchen, ein Zip-Format zu verwenden, in dem Sie die Dateien mit dem ZipEntry eingeben. Andernfalls ist das, was ich geschrieben habe, immer noch nur eine Anfrage. @ Ritu
HardCoded

Ist es für Sie möglich, eine Schleife außerhalb Ihrer Asynctask zu verwenden? Wenn Sie beispielsweise 3 Dateien zum Hochladen haben, führen Sie 3 Asynctask unabhängig voneinander aus. Auf diese Weise werden andere Bilder (Prozesse) weiter hochgeladen, wenn ein Problem für ein Bild gefunden wird (Upload-Vorgang). Während jede Asynctask endet, können Sie Zählen Sie nach einem Zähler in Ihrer Klasse und halten Sie bei Bedarf eine Verzögerungszeit (geschätzte Zeit) ein (um auf vorhandene Probleme beim Hochladen aufmerksam zu machen).
Maniaq

1
@maniaq Es ist kein optimaler Code, mehrere Asynctask für dieselbe Aufgabe auszuführen. Wir sollten Netzwerkanrufe vermeiden, wo immer wir können.
androidXP

0

FileinputStream unterstützt die ArrayList nicht. Mit ObjectOutputStream gibt es jedoch einen Ausweg . Außerdem wird Ihre ArrayList serialisiert. Überprüfen Sie die Änderungen im 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();

Viel Spaß beim Codieren :)


0

Sie sind sich nicht sicher, ob die Verwendung einer einzelnen asynchronen Aufgabe für Sie ein Muss ist.

Wie Sie sagten, funktioniert Ihr Code für Einzelbilder absolut einwandfrei. Um mehrere Dateien von arraylist hochzuladen, müssen Sie lediglich Ihre AsyncTask ein wenig ändern. Laden Sie einfach eine Datei nach der anderen hoch. Oder wenn Sie nicht einmal so viele Änderungen vornehmen möchten, deklarieren Sie einfach die globale Variable, die den Index des hochgeladenen Elements enthält, und erstellen Sie in OnPostExecute eine neue Instanz der asynchronen Aufgabe und übergeben Sie das nächste Element in der Arrayliste. Hoffe das ist klar.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.