I am uploading file from android to server using HttpUrlConnection. In normal case file upload successful and correct HTTP response code (200) and message captured. But server also validates the file being uploaded and can close connection anytime while uploading which prohibits client to upload unnecessary data to server.
In brief, Server has following validation:
1. File MimeType check:
If file MimeType isn't any image MimeType then close connection immediately throwing HTTP response code 415 and message "Unsupported Media Type". This check done immediately after request arrived in server.
2. File size check:
While upload is being progressed as stream, if file size more then 5 MB then server close connection by throwing HTTP response code 413 and message "Request entity too large"
Current status:
If file is image type AND less then 5 MB upload successful.
If file is not image type OR more then 5 MB unable to get HTTP response code (413 or 415) and message from HttpUrlConnection object. SocketException or IOException occurs and then invoking connection.getResponseCode() throws another exception. Why not connection object holds response code and message sent from server ?
Code:
package com.example.mahbub.fileuploadrnd;
import android.util.Log;
import com.example.mahbub.fileuploadrnd.util.MimeTypesUtil;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class FileUploadRequest {
private static final String DEBUG_TAG = "FileUploadRequest";
public static final int ERROR_OUT_OF_MEMORY = 0x00;
public static final int ERROR_UNDEFINED = 0x01;
public static final int ERROR_HTTP_ERROR = 0x02;
/**
* The pool of ASCII chars to be used for generating a multipart boundary.
*/
private final static char[] MULTIPART_CHARS =
"-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private static final String LINE_END = "\r\n";
private static final String TWO_HYPHENS = "--";
String url;
Map<String,String> mStringParts;
String filePartName;
String filePath;
UploadListener mListener;
public FileUploadRequest(String url, String filePartName, String filePath, UploadListener listener) {
this.url = url;
this.mStringParts = new HashMap<>();
this.filePartName = filePartName;
this.filePath = filePath;
this.mListener = listener;
}
public void execute() {
new Thread(new Runnable() {
#Override
public void run() {
executeRequest();
}
}).start();
}
public void addStringPart(String name, String value) {
this.mStringParts.put(name, value);
}
public void addStringParts(Map<String, String> parts) {
this.mStringParts.putAll(parts);
}
public interface UploadListener {
void onSuccess(int responseCode, String response);
void onError(int errorCode);
void transferred(long transferred, double progress);
}
private void executeRequest() {
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
String boundary = generateBoundary();
try {
URL url = new URL(this.url);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(4 * 1024);
// Enable POST method
connection.setRequestMethod("POST");
// Set header field value
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(TWO_HYPHENS + boundary + LINE_END);
// At first write all string parts
if(mStringParts.size() > 0) {
for (Map.Entry<String, String> entry : mStringParts.entrySet()) {
//entity.addTextBody(entry.getKey(), entry.getValue());
String partData = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END;
partData += entry.getValue() + LINE_END;
partData += (TWO_HYPHENS + boundary + LINE_END);
outputStream.writeBytes(partData);
}
}
// Write file data
File file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(file);
String partData = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", filePartName, file.getName()) + LINE_END;
partData += String.format("Content-Type: %s", getMimeType(file.getName()));
partData += LINE_END + LINE_END;
outputStream.writeBytes(partData);
// Input stream read buffer
byte[] buffer;
// Max possible buffer size
int maxBufferSize = 5 * 1024; // 5KB
// Bytes available to write in input stream
int bytesAvailable = fileInputStream.available();
Log.d(DEBUG_TAG, "File size: " + bytesAvailable);
// Buffer size
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
// Number of bytes read per read operation
int bytesRead;
// Allocate buffer
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
boolean errorOccured = false;
try {
while(bytesRead > 0) {
try {
outputStream.write(buffer, 0, bufferSize);
} catch (OutOfMemoryError e) {
Log.d(DEBUG_TAG, "OutOfMemoryError occurred");
errorOccured = true;
e.printStackTrace();
if(null != mListener) mListener.onError(ERROR_OUT_OF_MEMORY);
break;
} catch (SocketException e) {
Log.d(DEBUG_TAG, "SocketException occurred");
errorOccured = true;
e.printStackTrace();
if(null != mListener) mListener.onError(ERROR_OUT_OF_MEMORY);
break;
} catch (IOException e) {
Log.d(DEBUG_TAG, "IOException occurred");
errorOccured = true;
e.printStackTrace();
if(null != mListener) mListener.onError(ERROR_OUT_OF_MEMORY);
break;
}
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
double progress = ((double)(file.length()-bytesAvailable) / file.length());
Log.d(DEBUG_TAG, "Progress: " + progress);
if(null != mListener) mListener.transferred(file.length()-bytesAvailable, progress);
}
} catch (Exception e) {
e.printStackTrace();
if(null != mListener) mListener.onError(ERROR_UNDEFINED);
}
if(!errorOccured) {
outputStream.writeBytes(LINE_END);
outputStream.writeBytes(TWO_HYPHENS + boundary + TWO_HYPHENS + LINE_END);
}
// Responses from the server (code and message)
int responseCode = connection.getResponseCode();
String response = connection.getResponseMessage();
Log.d(DEBUG_TAG, "Server Response Code: " + responseCode);
Log.d(DEBUG_TAG, "Server Response Message: " + response);
InputStream inStream = null;
if(responseCode >= 200 && responseCode < 400) inStream = connection.getInputStream();
else inStream = connection.getErrorStream();
String responseString = readStream(inStream);
Log.d(DEBUG_TAG, "responseString: " + responseString);
if(responseCode >= 200 && responseCode < 400) {
if(null != mListener) mListener.onSuccess(responseCode, responseString);
} else {
if(null != mListener) mListener.onError(ERROR_HTTP_ERROR);
}
fileInputStream.close();
outputStream.flush();
outputStream.close();
outputStream = null;
inStream.close();
} catch (Exception e) {
e.printStackTrace();
if(null != mListener) mListener.onError(ERROR_UNDEFINED);
}
}
private String readStream(InputStream iStream) throws IOException {
//build a Stream Reader, it can read char by char
InputStreamReader iStreamReader = new InputStreamReader(iStream);
//build a buffered Reader, so that i can read whole line at once
BufferedReader bReader = new BufferedReader(iStreamReader);
String line = null;
StringBuilder builder = new StringBuilder();
while((line = bReader.readLine()) != null) { //Read till end
builder.append(line);
}
bReader.close(); //close all opened stuff
iStreamReader.close();
//iStream.close(); //EDIT: Let the creator of the stream close it!
// some readers may auto close the inner stream
return builder.toString();
}
private String generateBoundary() {
final StringBuilder buffer = new StringBuilder();
final Random rand = new Random();
final int count = rand.nextInt(11) + 30; // a random size from 30 to 40
for (int i = 0; i < count; i++) {
buffer.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
}
return buffer.toString();
}
/**
* Get mimeType based on file extension
* #param fileName
* #return
*/
private String getMimeType(String fileName) {
String[] parts = fileName.split("\\.");
if(parts.length <= 1) return null;
return MimeTypesUtil.getMimeType(parts[parts.length-1]);
}
}
Related
I am downloading a image file to save in apps internal storage using AsyncTask but I couldn't find the file in my emulator device manager.
here is the code can you tell me exactly where it is saving the image
private class ImageDownloader extends AsyncTask<String,Void,Bitmap>{
HttpURLConnection httpURLConnection;
#Override
protected Bitmap doInBackground(String... strings) {
try {
URL url = new URL(strings[0]);
httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = new BufferedInputStream(httpURLConnection.getInputStream());
Bitmap temp = BitmapFactory.decodeStream(inputStream);
return temp;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpURLConnection.disconnect();
}
return null;
}
In the below example, I will use a lengthy but detailed approach. This approach will enable you to give a file directory manually and allow you to save to a specified directory or path.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* A utility that downloads a file from a URL.
* #author www.codejava.net
*
*/
public class HttpDownloadUtility {
private static final int BUFFER_SIZE = 4096;
/**
* Downloads a file from a URL
* #param fileURL HTTP URL of the file to be downloaded
* #param saveDir path of the directory to save the file
* #throws IOException
*/
public static void downloadFile(String fileURL, String saveDir)
throws IOException {
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 10,
disposition.length() - 1);
}
} else {
// extracts file name from URL
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
fileURL.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
String saveFilePath = saveDir + File.separator + fileName;
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
System.out.println("File downloaded");
} else {
System.out.println("No file to download. Server replied HTTP code: " + responseCode);
}
httpConn.disconnect();
}
}
import java.io.*;
import java.net.*;
public class WebServer{
private void run(){
try {
ServerSocket serverSocket = new ServerSocket(5520);
while(true){
try {
Socket serverClient = serverSocket.accept();
WebServerThread wst = new WebServerThread(serverClient);
wst.start();
} catch (IOException evt) {
System.out.println("Error");
}
}
} catch (IOException evt) {
System.out.println("error");
}
}
public static void main(String[] args) {
WebServer ws = new WebServer();
System.out.println("Server is up and running.");
ws.run();
}
}
import java.io.*;
import java.net.*;
import java.lang.*;
class WebServerThread extends Thread {
Socket serverClient;
BufferedReader in = null;
public WebServerThread(Socket clientSocket) {
serverClient = clientSocket;
}
public void run() {
try {
in = new BufferedReader(new InputStreamReader(serverClient.getInputStream()));
//System.out.println(in.readLine());
HTTP http = new HTTP(in.readLine(), serverClient);
in.close();
serverClient.close();
} catch (IOException e) {
System.out.println("Error");
} catch (NullPointerException e){
System.out.println("bad");
}
}
}
import java.io.*;
import java.nio.Buffer;
import java.util.StringTokenizer;
import java.net.*;
public class HTTP {
String contentTypeLine;
String file;
String version = "HTTP/1.1";
//String crlf = "\\r\\n";
String statusLine;
String responseHeader;
String statusCodePhrase;
String headerFieldName = "Content-type: ";
String headerValue;
String header;
public HTTP(String request, Socket socket) throws IOException {
StringTokenizer st = new StringTokenizer(request);
st.nextToken();
file = "." + st.nextToken();
try {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
headerValue = contentType(file);
statusLine = "HTML/1.0 200 OK\r\n";
responseHeader = "Content-type: " + headerValue + "\r\n";
dos.writeBytes(statusLine);
dos.writeBytes(responseHeader);
dos.writeBytes("\r\n");
System.out.println(statusLine);
System.out.println(responseHeader);
System.out.println("Client requesting file: " + file);
writeEntityBody(file, bin, dos);
System.out.println("FIle: " + file + " sent successfully.");
} catch (FileNotFoundException evt) {
System.out.println(file + " not found.");
System.out.println("Requested file does not exist.");
statusCodePhrase = "404 Not Found";
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes("<HTML>" + "<HEAD><TITLE>Not Found</TITLE></HEAD>"
+ "<BODY>Not Found</BODY></HTML>");
} catch (IOException evt) {
System.out.println("Bad");
}
}
private void writeEntityBody(String file, BufferedInputStream bin, DataOutputStream dos) throws IOException {
int CHUNK_SIZE = 1024;
byte[] buffer = new byte[CHUNK_SIZE];
int len;
while ((len = bin.read(buffer)) != -1) {
dos.write(buffer, 0, len);
}
bin.close();
dos.flush();
dos.close();
}
private String contentType(String file){
String extension = file.split("\\.")[2];
if(extension.equals("htm") || extension.equals("html") || extension.equals("txt")){
contentTypeLine = "text/html";
}
else if(extension.equals("jpg") || extension.equals("gif") || extension.equals("png") || extension.equals("bmp") || extension.equals("pdf")) {
contentTypeLine = "image/bmp";
}
else{
return "application/octet-stream";
}
return contentTypeLine;
}
}
So basically, my server listens for a request from the client, which is the browser, so if I type "127.0.0.1:5520/test.txt" it connects to port 5520 and requests the file "test.txt".
In terms of listening for requests and starting threads, its fine. But in the HTTP class, when my program performs these lines:
headerValue = contentType(file);
statusLine = "HTML/1.0 200 OK\r\n";
responseHeader = "Content-type: " + headerValue + "\r\n";
dos.writeBytes(statusLine);
dos.writeBytes(responseHeader);
dos.writeBytes("\r\n");
That ideally should create the header and the browser should identify that. But the browser is just writing all of that as if it were part of the message body.
I've tried it on several different browsers and these were the results:
IE: Displays statusLine, responseHeader as if it were part of the message body and displays the contents of the file.
Firefox: Throws out statusLine, displays responseHeader as part of the message body and displays the content of the file.
Chrome: ERR_INVALID_HTTP_RESPONSE
I'm not sure why the browser can't identify the header.
Hint: the protocol is called "HTTP", not "HTML".
This question is a little bit long, so there might be confusions and in any case if you have, please don't hesitate to let me know..
I was trying to make a code to upload a video to the web server. In order to do so, I split the code's roles into three (in general, not including the details):
an activity that uploads a video and an inner class called VideoUploader that extends AsyncTask to execute the upload process,
a manager class called VideoManager.java that deals with uploading a video with the POST method,
and the PHP part that takes the POST video and stores it in the server.
Here is the uploadVideo() method inside the activity.
public void uploadVideo(final String stringPath) {
class VideoUploader extends AsyncTask<Void, Void, String> {
ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(UploadVideoActivity.this);
pDialog.setMessage("Uploading");
pDialog.setIndeterminate(true);
pDialog.setProgress(0);
pDialog.show();
final int totalProgressTime = 100;
final Thread thread = new Thread() {
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(200);
jumpTime += 5;
pDialog.setProgress(jumpTime);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pDialog.dismiss();
}
#Override
protected String doInBackground(Void... params) {
VideoManager videoManager = new VideoManager(getApplicationContext());
final String msg = videoManager.getUploadVideoResponse(stringPath);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
return msg;
}
}
VideoUploader uv = new VideoUploader();
uv.execute();
}
The following code is the VideoManager.java class.
public class VideoManager {
private Context context;
private int serverResponseCode;
private String urlUploadVideo = ServerURL.UPLOAD_VIDEO;
public VideoManager(Context context) {
this.context = context;
}
public String getUploadVideoResponse(String filePath) {
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
/*
* a buffer is a temporary memory area in which data is stored while it is being processed
* or transferred, especially one used while streaming video or downloading audio.
* here the maximum buffer size is 1024 bytes * 1024 bytes = 1048576 bytes ≈ 1.05 megabytes.
*/
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(filePath);
// check if the source file is a proper file.
if (!sourceFile.isFile()) {
Toast.makeText(context, "File does not exist.", Toast.LENGTH_SHORT).show();
return null;
}
try {
// an input stream that reads bytes from a file
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(urlUploadVideo);
conn = (HttpURLConnection) url.openConnection();
// allow the url connection input
conn.setDoInput(true);
// allow the url connection output
conn.setDoOutput(true);
// not allow the url connection to use cache
conn.setUseCaches(false);
conn.setRequestMethod("POST");
// set the value of the requested header field
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("myFile", filePath);
// a data output stream lets an application write primitive Java data types to an output stream in a portable way.
// an application can then use a data input stream to read the data back in.
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"myFile\";filename=\"" + filePath + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
Log.i("Huzza", "Initial .available : " + bytesAvailable);
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
serverResponseCode = conn.getResponseCode();
fileInputStream.close();
// flush the data output stream.
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
}
// if the server responds OK
String response;
if (serverResponseCode == 200) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
} catch (IOException e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
}
response = sb.toString();
return response;
} else {
response = "An error occurred while uploading the video.";
return response;
}
}
}
And finally this is the PHP side that takes the video and stores it in the server.
<?php
$base_location = dirname(__FILE__);
$directory = '/uploaded_videos/';
$location = $base_location . $directory;
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$file_name = $_FILES['video']['name'];
$file_size = $_FILES['video']['size'];
$file_type = $_FILES['video']['type'];
$temp_name = $_FILES['video']['tmp_name'];
move_uploaded_file($temp_name, $location.$file_name);
} else {
echo $location;
}
?>
If I run the programme and execute the uploadVideo() method, I manage to get the string value from the public String getUploadVideoResponse(String filePath) method like below.
From my diagnosis, now that I get the string response, the server response code is 200, which means that the request was successful. But I still fail to have the video file itself in the server. Can any superman find out the real matter here?
I run my java webserver on port 6799
My directory has a txt.txt file and pdf.pdf file
When I give localhost:6799/txt.txt, it gives perfect output saying
GET /txt.txt HTTP/1.1HTTP/1.0 200 OK
Content-type: text/plain
This is a very simple text file
But when I give localhost:6799/pdf.pdf from browser, it gives java.lang.NullPointerException
This is my code
import java.net.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
int port = 6799;
System.out.println("\nListening on port " + port);
ServerSocket listen = new ServerSocket(port);
while (true) {
Socket socket = listen.accept();
HttpRequest request = new HttpRequest(socket);
Thread thread = new Thread(request);
thread.start();
}
}
}
--
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;
public final class HttpRequest implements Runnable {
final String CRLF = "\r\n";
Socket socket;
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
#Override
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
BufferedReader br;
DataOutputStream dos;
try (InputStream is = socket.getInputStream()) {
br = new BufferedReader(new InputStreamReader(is));
String requestline = br.readLine();
System.out.println("\n" + requestline);
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(requestline);
StringTokenizer tokens = new StringTokenizer(requestline);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<HTML>"
+ "<HEAD><TITLE>Not Found</TITLE></HEAD>"
+ "<BODY>Not Found</BODY></HTML>";
}
dos.writeBytes(statusLine);
dos.writeBytes(contentTypeLine);
dos.writeBytes(CRLF);
if (fileExists) {
sendBytes(fis, dos);
fis.close();
} else {
dos.writeBytes(entityBody);
}
}
br.close();
dos.close();
socket.close();
}
private void sendBytes(FileInputStream fis, DataOutputStream dos) throws IOException {
byte[] buffer = new byte[4096];
int bytes = 0;
while ((bytes = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytes);
}
}
private String contentType(String fileName) {
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
}
if (fileName.endsWith(".gif")) {
return "image/gif";
}
if (fileName.endsWith(".txt")) {
return "text/plain";
}
if (fileName.endsWith(".pdf")) {
return "application/pdf";
}
return "application/octet-stream";
}
}
STACK TRACE
java.lang.NullPointerException
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:274)
at HttpRequest.processRequest(HttpRequest.java:65)
at HttpRequest.run(HttpRequest.java:20)
at java.lang.Thread.run(Thread.java:724)
At least one issue is this code:
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
BufferedReader will return null at the end of the stream, so calling .length() on a null object will yield a NullPointerException.
A more idiomatic way to write this is:
while ((headerLine = br.readLine()) != null && headerLine.length() != 0) {
System.out.println(headerLine);
}
...which takes advantage of short-circuit logic to not evaluate the second condition if the result of (headerLine = br.readLine()) is null.
It is happening because for some reason you have toggled comment on the following line:
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
Untoggle it and you're good!
I'm using htmlunit with httpclient. How can I limit the response body length of httpclient to say 1MB?
The trick is easy. You have to take the InputStream,read from it and stop reading when the limit is exceeded.
InputStream instream = method.getResponseBodyAsStream();
I have done an example tuning the apache example a bit.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
public class HttpClientTutorial {
private static String url = "http://www.apache.com";
private static final int LIMIT = 1024*1024;//set to 1MB
public static void main(String[] args) {
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
//byte[] responseBody = method.getResponseBody();
byte[] responseBody = null;
InputStream instream = method.getResponseBodyAsStream();
if (instream != null) {
long contentLength = method.getResponseContentLength();
if (contentLength < Integer.MAX_VALUE) { //guard below cast from overflow
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
int total = 0;
while ((len = instream.read(buffer)) > 0 && total<LIMIT) {
outstream.write(buffer, 0, len);
total+= len;
}
responseBody = outstream.toByteArray();
outstream.close();
instream.close();
System.out.println(new String(responseBody));
}
}
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}
}
I hope this helps.
You could use BoundedInputStream from Apache Commons.
This is a stream that will only supply bytes up to a certain length - if its position goes above that, it will stop.