Mohanakrrishna Mohanakrrishna - 2 months ago 11
Java Question

Why does when sending a file in multipart/form-data in java we have to use both a Writer and a OutputStream?

Hi I have seen many sample codes working for sending a file in multipart/form-data in java.
But they have used both Writer and an OutputStream.
Why can't they use just use one of them?

Here is the sample code they have sent

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainClass_External2 {
public static void main(String[] args){
try{
// Connect to the web server endpoint
URL serverUrl =
new URL("http://posttestserver.com/post.php?dir=example");
HttpURLConnection urlConnection = (HttpURLConnection)serverUrl.openConnection();

String boundaryString = "----SomeRandomText";
String fileUrl = "abc.txt";
File logFileToUpload = new File(fileUrl);

// Indicate that we want to write to the HTTP request body
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.addRequestProperty("Content-Type","multipart/form-data; boundary=" + boundaryString);

// Indicate that we want to write some data as the HTTP request body
urlConnection.setDoOutput(true);

OutputStream outputStreamToRequestBody = urlConnection.getOutputStream();
BufferedWriter httpRequestBodyWriter =
new BufferedWriter(new OutputStreamWriter(outputStreamToRequestBody));

// Include value from the myFileDescription text area in the post data
httpRequestBodyWriter.write("\n\n--" + boundaryString + "\n");
httpRequestBodyWriter.write("Content-Disposition: form-data; name=\"myFileDescription\"");
httpRequestBodyWriter.write("\n\n");
httpRequestBodyWriter.write("Log file for 20150208");

// Include the section to describe the file
httpRequestBodyWriter.write("\n--" + boundaryString + "\n");
httpRequestBodyWriter.write("Content-Disposition: form-data;"
+ "name=\"myFile\";"
+ "filename=\""+ logFileToUpload.getName() +"\""
+ "\nContent-Type: text/plain\n\n");
httpRequestBodyWriter.flush();

// Write the actual file contents
FileInputStream inputStreamToLogFile = new FileInputStream(logFileToUpload);

int bytesRead;
byte[] dataBuffer = new byte[1024];
while((bytesRead = inputStreamToLogFile.read(dataBuffer)) != -1){
outputStreamToRequestBody.write(dataBuffer, 0, bytesRead);
}

// Mark the end of the multipart http request
httpRequestBodyWriter.write("\n--" + boundaryString + "--\n");
httpRequestBodyWriter.flush();

// Close the streams
outputStreamToRequestBody.close();
httpRequestBodyWriter.close();

// Read response from web server, which will trigger the multipart HTTP request to be sent.
BufferedReader httpResponseReader =
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String lineRead;
while((lineRead = httpResponseReader.readLine()) != null) {
System.out.println(lineRead);
}
}catch (Exception e){
e.printStackTrace();
}
}
}

Answer

Basically, the response contains both text and binary data, so using both a Writer and an OutputStream makes perfect sense.

The writer just wraps the output stream, and is used to write text. The output stream itself is used to write the binary data.

Why can't they use just use one of them?

Using just an OutputStream would make it more painful to write the text. Using just a Writer would be inappropriate when binary data needs to be written.