อัปโหลด arraylist โดยใช้ httpurlconnection multipart / form-data


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 ถูกคัดค้านใช้ชุดติดตั้งเพิ่มเติมหรือ
ไลบรารี่

คุณสามารถใช้ชุดติดตั้งเพิ่มเติมและอัปโหลดภาพหลายภาพในคำขอเดียว
Priyankagb

คำตอบ:


4

โปรดทราบว่าฉันไม่ได้ลองถ้ารหัสนี้ใช้งานได้จริงกับ HttpURLConnection แต่มันควร

จากสิ่งที่ฉันอ่านจากอินเทอร์เน็ตคุณยังสามารถใช้วงวนนั้นที่คุณพูดถึง แต่ด้วยการดัดแปลงบางอย่าง

ฉันติดตามการสอนเกี่ยวกับmultipart / form-dataที่นี่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จะมีmultipart / form-dataที่คุณต้องการส่งด้วย HttpURLConnection ของคุณ

ฉันไม่ได้อยู่ที่นี่มานานแล้ว บอกฉันหากคุณต้องการข้อมูลจำเพาะเพิ่มเติมหรือฉันต้องการชี้แจงข้อความของฉัน: D


ถ้าฉันเรียกใช้ลูปแล้วฉันต้องทำการร้องขอหลายครั้งสำหรับการอัปโหลดอาร์เรย์ ฉันต้องอัปโหลดอาร์เรย์ไปยังเซิร์ฟเวอร์ในการโทรครั้งเดียว
Ritu

จากสิ่งที่ฉันเข้าใจคือคุณต้องการส่งภาพไปยังเซิร์ฟเวอร์ในการโทร HttpURLConnection เดียว คุณสามารถลองใช้รูปแบบ zip ที่คุณป้อนไฟล์ด้วย ZipEntry ไม่เช่นนั้นสิ่งที่ฉันเขียนจะยังคงเป็นคำขอเดียวเท่านั้น @Ritu
HardCoded

เป็นไปได้ไหมสำหรับคุณที่ใช้ลูปนอก asynctask ของคุณ? ตัวอย่างเช่นหากคุณมีไฟล์ 3 ไฟล์สำหรับการอัปโหลดคุณเรียกใช้ 3 asynctask อย่างอิสระในลักษณะนี้หากพบปัญหาหรือปัญหาสำหรับรูปภาพ (กระบวนการอัปโหลด) รูปภาพอื่น ๆ (กระบวนการ) ยังคงอัปโหลดต่อไป นับตามเคาน์เตอร์ในชั้นเรียนของคุณและรักษาเวลาที่ล่าช้า (เวลาโดยประมาณ) หากจำเป็น (สำหรับการแจ้งเตือนสำหรับปัญหาที่มีอยู่ในการอัปโหลด)
maniaq

1
@maniaq ไม่ใช่รหัสที่ดีที่สุดในการรัน asynctask หลายรายการสำหรับงานเดียวกัน เราควรหลีกเลี่ยงการโทรผ่านเครือข่ายทุกที่ที่ทำได้
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();

Happy Coding :)


0

ไม่แน่ใจว่าการใช้งาน async เดียวเป็นสิ่งจำเป็นสำหรับคุณหรือไม่

อย่างที่คุณพูดรหัสของคุณใช้ได้ดีกับภาพเดียว ดังนั้นสำหรับการอัปโหลดหลายไฟล์จาก arraylist คุณเพียงแค่ต้องปรับเปลี่ยน AsyncTask ของคุณสักเล็กน้อย เพียงอัปโหลดไฟล์เดียวหลังจากนั้นอีกไฟล์หรือหากคุณไม่ต้องการทำการเปลี่ยนแปลงมากนักเพียงแค่ประกาศตัวแปรทั่วโลกที่ถือดัชนีของรายการที่กำลังอัปโหลดและใน OnPostExecute ให้สร้างอินสแตนซ์ใหม่ของภารกิจ async และส่งรายการถัดไปในรายการอาร์เรย์ หวังว่านี่จะชัดเจน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.