Tải lên danh sách mảng bằng cách sử dụng đa dữ liệu / biểu mẫu dữ liệu httpurlconnection


11

Tôi cần tải Arraylisthình ảnh lên máy chủ mà không cần sử dụng bất kỳ thư viện nào. Tôi đang sử dụng Asynctaskđể tải lên một hình ảnh duy nhất và nó hoạt động hoàn hảo với sự trợ giúp của dữ liệu đa dữ liệu / biểu mẫu httpurlconnection. Bây giờ tôi cần thay đổi mã của mình để tải lên nhiều tệp thuộc bất kỳ loại nào bằng cách sử dụng Arraylist<String>nhưng vấn đề của tôi là danh sách mảng FileinputStreamkhông hỗ trợ của mã hiện tại và tôi không biết nên sử dụng cái gì thay vì Fileinputstreamtải danh sách mảng lên máy chủ và tôi không muốn sử dụng bất kỳ thư viện cho việc này.

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


}

Tôi cũng đã cố gắng đưa FileInputStreamvào vòng lặp nhưng tải lên hình ảnh vào nhiều yêu cầu không phải là điều tôi muốn. Máy chủ của tôi yêu cầu ứng dụng của bạn thực hiện một yêu cầu duy nhất cho n số lượng hình ảnh. Bất kỳ trợ giúp sẽ được đánh giá cao nhưng không sử dụng bất kỳ thư viện


Các lớp http không được dùng nữa, sử dụng trang bị thêm hoặc thư viện khác
Jaiprakash Soni

bạn có thể sử dụng trang bị thêm và tải lên nhiều hình ảnh trong một yêu cầu
Priyankagb

Câu trả lời:


4

LƯU Ý rằng tôi đã không thử nếu mã này tình cờ hoạt động với kết nối httpURLC nhưng nó nên.

Từ những gì tôi đã đọc từ internet, bạn vẫn có thể sử dụng vòng lặp mà bạn đã đề cập nhưng với một số sửa đổi.

Tôi đã làm theo hướng dẫn về đa dữ liệu / biểu mẫu dữ liệu ở đây dev.to , để làm cho bài viết này trở nên thú vị hơn, tôi sẽ cho bạn biết phương pháp này là gì sẽ xảy ra.

Đa dữ liệu / biểu mẫu dữ liệu được gửi như thế này

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

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

data2
--boundary--

Những gì tôi sẽ làm là tạo ra một phương thức mới nhưng bạn chỉ có thể viết mã trong phương thức đã có của bạn.

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

Bạn muốn viết là ranh giới theo sau là bố trí và sau đó là dữ liệu . Làm điều đó cho tất cả các tập tin và sau đó bạn gửi ranh giới đóng . Điều này sẽ tạo ra cấu trúc đa dữ liệu / biểu mẫu dữ liệu mà bạn muốn.

Trong mã psudo, điều này sẽ là

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

Mã có thể được viết như thế này, đầu tiên bạn xác định các biến của mình

ByteArrayOutputStream message = null;
DataOutputStream stream = null;

FileInputStream fileInputStream;

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

Đây là nơi dữ liệu sẽ được tạo ra. Nó bắt đầu với việc nối ranh giới và sau đó đọc dữ liệu. Dữ liệu đó được ghi vào luồng và bạn tiếp tục vòng lặp cho tất cả các tệp / hình ảnh.

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

Bây giờ, mảng byte sendDatasẽ chứa nhiều dữ liệu / biểu mẫu mà bạn cần gửi cùng với kết nối httpURLC của bạn.

Tôi đã không hoạt động ở đây trong một thời gian dài. Hãy cho tôi biết nếu bạn cần thêm một số đặc điểm kỹ thuật hoặc tôi làm rõ văn bản của mình: D


Nếu tôi chạy vòng lặp thì tôi cần phải thực hiện nhiều yêu cầu để tải lên mảng. Tôi cần tải một mảng lên máy chủ trong một cuộc gọi.
Ritu

Từ những gì tôi nói là bạn muốn gửi n hình ảnh đến máy chủ trong một cuộc gọi kết nối httpURLC. Bạn có thể thử sử dụng định dạng zip trong đó bạn nhập các tệp bằng ZipEntry nếu không những gì tôi đã viết sẽ vẫn chỉ là một yêu cầu. @Ritu
hardcoded

Có thể cho bạn sử dụng một vòng lặp bên ngoài asynctask của bạn? Ví dụ. Nếu bạn có 3 tệp để tải lên, bạn thực hiện 3 asynctask một cách độc lập. Theo cách này, nếu một vấn đề hoặc vấn đề được tìm thấy cho một hình ảnh (quá trình tải lên), các hình ảnh (quy trình) khác sẽ tiếp tục tải lên. đếm bởi một bộ đếm trong lớp của bạn và giữ thời gian trì hoãn (thời gian ước tính) nếu cần (để cảnh báo về sự cố hiện có trong việc tải lên).
maniaq

1
@maniaq Đó không phải là mã tối ưu để chạy nhiều asynctask cho cùng một tác vụ. Chúng ta nên tránh cuộc gọi mạng bất cứ nơi nào chúng ta có thể.
androidXP

0

FileinputStream không hỗ trợ ArrayList. Nhưng có một cách xung quanh bằng cách sử dụng ObjectOutputStream . Nó cũng sẽ tuần tự hóa ArrayList của bạn. Kiểm tra các thay đổi trong mã.

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

Chúc mừng mã hóa :)


0

Không chắc chắn nếu sử dụng tác vụ async duy nhất là phải cho bạn.

Như bạn đã nói, mã của bạn hoạt động hoàn toàn tốt cho hình ảnh duy nhất. Vì vậy, để tải lên nhiều tệp từ danh sách mảng, bạn chỉ cần sửa đổi AsyncTask một chút. Chỉ cần tải lên một tệp khác hoặc nếu bạn thậm chí không muốn thực hiện sửa đổi đó, chỉ cần khai báo biến toàn cục giữ chỉ mục của mục đang được tải lên và trong OnPostExecute tạo phiên bản mới của tác vụ async và chuyển mục tiếp theo trong danh sách mảng. Hy vọng điều này là rõ ràng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.