httpurlconnection multipart / form-data를 사용하여 배열 목록 업로드


11

Arraylist라이브러리를 사용하지 않고 이미지를 서버 에 업로드해야합니다 . 내가 사용하고 Asynctask하나의 이미지를 업로드 할 수 있으며, HttpURLConnection의 다중 / 폼 데이터의 도움으로 완벽하게 작동합니다. 이제 코드를 변경하여 모든 유형의 여러 파일을 사용하여 업로드해야 Arraylist<String>하지만 문제는 기존 코드가 FileinputStreamarraylist를 지원하지 않으며 Fileinputstreamarraylist를 서버에 업로드 하는 대신 무엇을 사용 해야할지 모르겠습니다. 이 라이브러리를 사용하고 싶습니다.

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과 정확하게 작동한다면 시도하지 않았지만 참고해야합니다.

인터넷에서 읽은 내용에서 언급 한 루프를 여전히 사용할 수 있지만 몇 가지 수정 사항이 있습니다.

나는 multipart / form-data here 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)

당신 은 처분 다음에 데이터가 따르는 경계 입니다. 모든 파일에 대해 그런 다음 닫는 경계 를 보냅니다 . 이것은 당신이 원하는 multipart / form-data 구조를 생성 할 것 입니다.

의사 코드에서 이것은

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과 함께 보내야 하는 multipart / form-data 가 포함됩니다 .

나는 오랫동안 여기에서 활동적이지 않았습니다. 더 많은 사양이 필요하거나 내 텍스트를 분명히 밝히면 알려주십시오.


루프를 실행하면 배열 업로드를 여러 번 요청해야합니다. 단일 호출로 서버에 배열을 업로드해야합니다.
리투

내가 이해 한 것은 단일 HttpURLConnection 호출로 n 개의 이미지를 서버에 보내고 싶다는 것입니다. ZipEntry로 파일을 입력하는 zip 형식을 사용해보십시오. 그렇지 않으면 내가 쓴 것은 여전히 ​​하나의 요청 일뿐입니다. @Ritu
하드

asynctask 외부에서 루프를 사용할 수 있습니까? 예를 들어 업로드 할 파일이 3 개인 경우 3 비동기 작업을 독립적으로 실행합니다.이 방법으로 이미지 (업로드 프로세스)에 문제 또는 문제가 발견되면 다른 이미지 (프로세스)가 계속 업로드됩니다. 모든 비동기 작업이 종료되는 동안 수업 시간에 카운터로 계산하고 필요한 경우 지연 시간 (예상 시간)을 유지하십시오 (업로드 문제가 있음을 경고하기 위해).
maniaq

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

단일 비동기 작업을 사용해야하는지 확실하지 않습니다.

말했듯이 코드는 단일 이미지에 완벽하게 작동합니다. 따라서 arraylist에서 여러 파일을 업로드하려면 AsyncTask를 약간 수정하면됩니다. 한 파일을 다른 파일 로 업로드하기 만해도 수정을 많이하고 싶지 않다면 업로드중인 항목의 인덱스를 보유하는 전역 변수를 선언하고 OnPostExecute에서 비동기 작업의 새 인스턴스를 만들고 arraylist의 다음 항목을 전달하십시오. 이것이 분명하기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.