Unggah daftar array menggunakan httpurlconnection multipart / form-data

11

Saya perlu mengunggah Arraylistgambar ke server tanpa menggunakan perpustakaan apa pun. Saya menggunakan Asynctaskuntuk mengunggah satu gambar dan itu berfungsi dengan baik dengan bantuan httpurlconnection multipart / form-data. Sekarang saya perlu mengubah kode saya untuk mengunggah beberapa file jenis apa pun dengan menggunakan Arraylist<String>tetapi masalah saya adalah kode yang ada FileinputStreamtidak mendukung daftar array dan saya tidak tahu apa yang harus digunakan daripada Fileinputstreammengunggah daftar array ke server dan saya tidak ingin menggunakan perpustakaan apa pun untuk ini juga.

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


}

Saya juga mencoba memasukkan FileInputStreamke dalam lingkaran tetapi mengunggah gambar ke beberapa permintaan bukanlah yang saya inginkan. Server saya membutuhkan aplikasi untuk membuat satu permintaan untuk sejumlah gambar. Bantuan apa pun akan dihargai tetapi tanpa menggunakan perpustakaan apa pun

Ritu
sumber
Kelas Http sudah usang, gunakan retrofit atau perpustakaan lainnya
Jaiprakash Soni
Anda dapat menggunakan retrofit dan mengunggah banyak gambar dalam satu permintaan
Priyankagb

Jawaban:

4

CATATAN bahwa saya belum mencoba jika kode ini secara aktual berfungsi dengan HttpURLConnection tetapi seharusnya.

Dari apa yang saya baca dari internet Anda masih dapat menggunakan loop yang Anda sebutkan tetapi dengan beberapa modifikasi.

Saya mengikuti tutorial tentang multipart / form-data di sini dev.to , untuk menjadikan ini lebih sebagai posting pembelajaran, saya akan memberi tahu Anda apa metode ini yang harus terjadi.

The multipart / form-data yang dikirim seperti ini

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

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

data2
--boundary--

Apa yang akan saya lakukan adalah membuat metode baru tetapi Anda bisa menulis kode dengan metode yang sudah ada.

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

Yang ingin Anda tulis adalah batas diikuti oleh disposisi dan kemudian data . Lakukan itu untuk semua file dan kemudian Anda mengirim batas penutupan . Ini akan menghasilkan struktur multipart / formulir-data yang Anda inginkan.

Dalam kode-psudo ini akan menjadi

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

Kode dapat ditulis seperti ini, pertama Anda mendefinisikan variabel Anda

ByteArrayOutputStream message = null;
DataOutputStream stream = null;

FileInputStream fileInputStream;

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

Di sinilah data akan dihasilkan. Dimulai dengan menyatukan batas dan kemudian membaca data. Data itu ditulis ke stream dan Anda melanjutkan loop untuk semua file / gambar.

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

Sekarang array byte sendDataakan berisi multipart / form-data yang perlu Anda kirim dengan HttpURLConnection Anda.

Saya sudah tidak aktif di sini untuk waktu yang lama. Beri tahu saya jika Anda memerlukan spesifikasi lebih lanjut atau saya mengklarifikasi teks saya: D

HardCode
sumber
Jika saya menjalankan loop maka saya perlu membuat beberapa permintaan untuk mengunggah array. Saya perlu mengunggah array ke server dalam satu panggilan.
Ritu
Dari apa yang saya mengerti adalah bahwa Anda ingin mengirim gambar ke server dalam satu panggilan HttpURLConnection. Anda dapat mencoba menggunakan format zip di mana Anda memasukkan file dengan ZipEntry jika tidak, apa yang saya tulis hanya akan menjadi satu permintaan. @Ritu
HardCoded
Apakah mungkin bagi Anda yang menggunakan loop di luar asynctask Anda? Misalnya, jika Anda memiliki 3 file untuk diunggah, Anda menjalankan 3 asynctask secara mandiri. Dengan cara ini jika masalah atau masalah ditemukan untuk suatu gambar (proses pengunggahan), gambar (proses) lainnya terus diunggah. Sementara setiap asynctask berakhir Anda dapat hitung dengan penghitung di kelas Anda dan pertahankan waktu tunda (perkiraan waktu) jika perlu (untuk memberi tahu ada masalah dalam mengunggah).
maniaq
1
@maniaq bukan kode optimal untuk menjalankan beberapa asynctask untuk tugas yang sama. Kita harus menghindari panggilan jaringan di mana pun kita bisa.
androidXP
0

FileinputStream tidak mendukung ArrayList. Tapi ada jalan keluar dengan menggunakan ObjectOutputStream . Ini juga akan membuat serial ArrayList Anda. Periksa perubahan dalam kode.

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

Selamat Coding :)

Attiq ur Rehman
sumber
0

Tidak yakin apakah menggunakan tugas async tunggal adalah suatu keharusan bagi Anda.

Seperti yang Anda katakan, kode Anda berfungsi dengan sangat baik untuk gambar tunggal. Jadi untuk mengunggah banyak file dari daftar array, Anda hanya perlu sedikit memodifikasi AsyncTask Anda. Cukup unggah satu file demi satu atau jika Anda bahkan tidak ingin melakukan banyak modifikasi, cukup deklarasikan variabel global yang menyimpan indeks item yang sedang diunggah dan di OnPostExecute buat instance baru dari tugas async dan berikan item berikutnya dalam daftar array. Semoga ini jelas.

mayank1513
sumber