使用httpurlconnection multipart / form-data上传arraylist


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循环,但是将图像上传到多个请求中并不是我想要的。我的服务器require的应用程序对n个图像发出单个请求。任何帮助将不胜感激,但无需使用任何库


不推荐使用Http类,请使用改造或其他库
Jaiprakash Soni

您可以使用改造并在单个请求中上传多个图像
Priyankagb

Answers:


4

注意,如果该代码正确地与HttpURLConnection一起使用,我还没有尝试过,但是应该可以。

从我从互联网上读取的内容来看,您仍然可以使用您提到的那个循环,但需要进行一些修改。

我在dev.to上的multipart / form-data教程中进行了跟踪,以使本文更具学习性,我将告诉您该方法应该发生什么。

多部分/格式数据发送这样

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

我已经很长时间没有在这里活动了。告诉我您是否需要更多说明,或者我要澄清我的文字:D


如果我运行循环,那么我需要发出多个数组上传请求。我需要在单个调用中将数组上载到服务器。
Ritu

据我所知,您想通过单个HttpURLConnection调用将n个图像发送到服务器。您可以尝试使用zip格式,在其中使用ZipEntry输入文件,否则我写的内容仍然只是一个请求。@Ritu
HardCoded

您是否有可能在asynctask之外使用循环?例如,如果您有3个文件要上传,则可以独立执行3个asynctask。以这种方式,如果发现某个图像有问题(上传过程),则其他图像(过程)仍会继续上传。尽管每个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();

快乐编码:)


0

不确定是否必须使用单个异步任务。

如您所说,您的代码对于单个图像绝对有效。因此,要从arraylist上传多个文件,您只需要稍微修改一下AsyncTask。只是一个接一个地上传一个文件,或者,如果您不想做那么多修改,只需声明一个全局变量,该变量保存要上传项目的索引,然后在OnPostExecute中创建异步任务的新实例,并在arraylist中传递下一个项目。希望这很清楚。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.