Завантажте масив архівів за допомогою багаточастотних / форм-даних httpurlconnection


11

Мені потрібно завантажувати Arraylistзображення на сервер, не використовуючи жодної бібліотеки. Я використовую Asynctaskдля завантаження одного зображення, і він ідеально працює за допомогою httpurlconnection multipart / form-data. Тепер мені потрібно змінити код, щоб завантажити декілька файлів будь-якого типу за допомогоюArraylist<String> але моя проблема полягає в тому, що існуючий код FileinputStreamне підтримує arraylist, і я не маю уявлення, що використовувати замість Fileinputstreamзавантаження arraylist на сервер, і я не хочу також використовувати будь-яку бібліотеку для цього.

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


}

Я також намагався поставити FileInputStream цикл, але завантажувати зображення в декілька запитів - це не те, що я хочу. Мій сервер вимагає від програми зробити єдиний запит на n кількість зображень. Будь-яка допомога буде вдячна, але без використання жодної бібліотеки


Класи Http застарілі, використовуйте модернізацію чи іншу бібліотеку
Jaiprakash Soni

ви можете використовувати модернізацію та завантажувати кілька зображень в одному запиті
Priyankagb

Відповіді:


4

Зверніть увагу, що я не намагався, якщо цей код фактично працює з HttpURLConnection, але повинен.

З того, що я читав з Інтернету, ви все ще можете використовувати цей цикл, який ви згадали, але з деякими модифікаціями.

Я слідував підручником із багатоповерхових / форм-даних тут dev.to , щоб зробити це більше навчальним дописом , я розповім, що це метод, що має відбутися.

Дані про множину / форму надсилаються таким чином

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

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

data2
--boundary--

Що я б робив, це створити новий метод, але ви можете просто написати код у свій уже існуючий метод.

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

Ви хочете написати - це межа, за якою слідує диспозиція, а потім дані . Зробіть це для всіх файлів, а потім ви надішліть межу закриття . Це призведе до створення структуру даних багатосторонньої форми / форми .

У psudo-коді це було б

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

Код можна записати так, спочатку визначте свої змінні

ByteArrayOutputStream message = null;
DataOutputStream stream = null;

FileInputStream fileInputStream;

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

Ось де дані будуть генеруватися. Він починається з об'єднання межі, а потім з читання даних. Ці дані записуються в потік, і ви продовжуєте цикл для всіх файлів / зображень.

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

Тепер байтовий масив sendDataбуде містити дані багаточастинних / форм-форм, які вам потрібно надіслати за допомогою свого HttpURLConnection.

Я давно не був таким активним. Скажіть, якщо вам потрібна ще якась специфікація чи я уточнюю свій текст: D


Якщо я запускаю цикл, то мені потрібно зробити кілька запитів на завантаження масиву. Мені потрібно завантажувати масив на сервер за один виклик.
Ritu

З того, що я вважаю, що ви хочете відправити n зображень на сервер за один виклик HttpURLConnection. Ви можете спробувати використовувати формат zip, коли ви вводите файли за допомогою ZipEntry, інакше те, що я написав, все одно буде лише одним запитом. @Ritu
HardCoded

Чи можливо для вас, що використовуєте петлю за межами вашого асинтакта? .Заприклад, якщо у вас є 3 файли для завантаження, ви виконайте 3 асинтакти, самостійно. Таким чином, якщо для зображення знайдеться проблема (процес завантаження), інші зображення (процеси) продовжують завантажувати. Хоча кожен асинктаск закінчується, ви могли б підраховують за лічильником у своєму класі та зберігають час затримки (орієнтовний час), якщо це потрібно (для оповіщення про наявність проблеми при завантаженні).
маніяк

1
@maniaq це не оптимальний код для запуску декількох асинтакцій для одного завдання. Ми повинні уникати мережевого дзвінка, де тільки можемо.
androidXP

0

FileinputStream не підтримує ArrayList. Але є спосіб подолати, використовуючи ObjectOutputStream . Він також буде серіалізувати ваш ArrayList. Перевірте зміни в коді.

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

Щасливе кодування :)


0

Не впевнений, що використання одного завдання асинхрування є обов'язковим для вас.

Як ви сказали, ваш код працює абсолютно добре для одного зображення. Отже, для завантаження декількох файлів з масиву архіву потрібно просто трохи змінити свій AsyncTask. Просто завантажте один файл за іншим Або якщо ви навіть не хочете робити такої модифікації, просто оголосіть глобальну змінну, що містить індекс завантажуваного елемента, і в OnPostExecute створіть новий екземпляр завдання async та передайте наступний елемент у масив архіву. Сподіваюся, це зрозуміло.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.