How can I include css file using com.sun.net.httpserver? - java

I'm trying to write a simple http server, using com.sun.net.httpserver class. I send html file (index.html) to browser on startup, but I don't know how to include an external css file. It works when css code is placed inside html file. I know, that browser should send a request, asking server for css file, but I'm not sure how to receive this request and send back this file to browser. I attach a fragment of my code below, if it could be helpful.
private void startServer()
{
try
{
server = HttpServer.create(new InetSocketAddress(8000), 0);
}
catch (IOException e)
{
System.err.println("Exception in class : " + e.getMessage());
}
server.createContext("/", new indexHandler());
server.setExecutor(null);
server.start();
}
private static class indexHandler implements HttpHandler
{
public void handle(HttpExchange httpExchange) throws IOException
{
Headers header = httpExchange.getResponseHeaders();
header.add("Content-Type", "text/html");
sendIndexFile(httpExchange);
}
}
static private void sendIndexFile(HttpExchange httpExchange) throws IOException
{
File indexFile = new File(getIndexFilePath());
byte [] indexFileByteArray = new byte[(int)indexFile.length()];
BufferedInputStream requestStream = new BufferedInputStream(new FileInputStream(indexFile));
requestStream.read(indexFileByteArray, 0, indexFileByteArray.length);
httpExchange.sendResponseHeaders(200, indexFile.length());
OutputStream responseStream = httpExchange.getResponseBody();
responseStream.write(indexFileByteArray, 0, indexFileByteArray.length);
responseStream.close();
}

There is no built-in method for handling static content. You have two options.
Either use a light-weight webserver for static content like nginx, but than distribution of your application will be more difficult.
Or create your own file serving classes. For that, you have to create a new context in your web server:
int port = 8080;
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
// ... more server contexts
server.createContext("/static", new StaticFileServer());
And than create the class that will serve your static files.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
#SuppressWarnings("restriction")
public class StaticFileServer implements HttpHandler {
#Override
public void handle(HttpExchange exchange) throws IOException {
String fileId = exchange.getRequestURI().getPath();
File file = getFile(fileId);
if (file == null) {
String response = "Error 404 File not found.";
exchange.sendResponseHeaders(404, response.length());
OutputStream output = exchange.getResponseBody();
output.write(response.getBytes());
output.flush();
output.close();
} else {
exchange.sendResponseHeaders(200, 0);
OutputStream output = exchange.getResponseBody();
FileInputStream fs = new FileInputStream(file);
final byte[] buffer = new byte[0x10000];
int count = 0;
while ((count = fs.read(buffer)) >= 0) {
output.write(buffer, 0, count);
}
output.flush();
output.close();
fs.close();
}
}
private File getFile(String fileId) {
// TODO retrieve the file associated with the id
return null;
}
}
For the method getFile(String fileId); you can implement any way of retrieving the file associated with the fileId. A good option is to create a file structure mirroring the URL hierarchy. If you don't have many files, than you can use a HashMap to store valid id-file pairs.

Related

Java opens URL to save file to specific folder

I'm trying to code based on the manual operation. For manual, I have a URL and when I paste the URL to the Chrome browser, the browser automatically downloads the PDF file from that URL and save to folder "download" without prompting any user input. With Code, I'm able to accomplish the same thing as the manual operation. However I would like the code to save the PDF into specific folder instead of default folder "download". Is it possible to do that?
public static void browseURL() {
try {
String url ="mycompanyURL";
System.out.println("url " + url );
Desktop desktop = Desktop.getDesktop();
URI uri = new URI (url);
desktop.browse(uri);
}catch(Exception err) {
System.out.println("exception " + err.getMessage());
}
}
When I had to do that in old versions of Java, I used the following snippet (pure Java, source: Baeldung).
public void streamFromUrl(String downloadUrl, String filePath) throws IOException {
File file = new File(filePath);
try (BufferedInputStream in = new BufferedInputStream(new URL(downloadUrl).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(file)) {
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
}
}
The above opens an input stream on the URL, and outputs the bytes of such stream into a file output stream (where the file is wherever you wish).
Alternatively, there are many libraries doing that in one/two liners (the article I posted shows some of those alternatives).
Also, starting from more recent versions of Java, there are other shorter options:
public void streamFromUrl(String downloadUrl, String filePath) throws IOException {
try (InputStream in = new URL(downloadUrl).openStream()) {
Files.copy(in, Paths.get(new File(filePath)), StandardCopyOption.REPLACE_EXISTING);
}
}
Depending on the version of Java you have, you may pick one of those. Generally speaking, I suggest you reading through the Baeldung's article and check the one that best suits for you.
Here you go. Handles redirects and so on can use and modify as you wish. Have fun with it. All in native Java. Did write this to download some media easily. This can also download media like images, videos and documents.
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.Builder;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Files;
import java.nio.file.Path;
public class Downloader {
public static void download(String url) {
final HttpClient hc = HttpClient.newHttpClient();
final Builder requestBuilder = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1);
Path path = Path.of("myfilepath");
handleGet(hc, "myfile.pdf", "myurl.com", path, requestBuilder);
}
private static void handleGet(
final HttpClient hc,
final String fileName,
final String url,
final Path filePath,
final Builder requestBuilder
) {
final HttpRequest request = requestBuilder.uri(URI.create(url)).build();
hc.sendAsync(request, BodyHandlers.ofInputStream())
.thenApply(resp -> {
int sc = resp.statusCode();
System.out.println("STATUSCODE: "+sc+" for url '"+url+"'");
if(sc >= 200 && sc < 300) return resp;
if(sc == 302) {
System.out.println("Handling 302...");
String newUrl = resp.headers().firstValue("location").get();
handleGet(hc, fileName, newUrl, filePath, requestBuilder);
}
return resp;
})
.thenAccept(resp -> {
int sc = resp.statusCode();
if(sc >= 200 && sc < 300) {
try {
System.out.println("Im fine here");
Files.copy(resp.body(), filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
System.err.println("STATUSCODE: "+ sc +" for file "+ fileName);
}
}).join();
}
}

New file is getting created during FTP download

I'm trying to download a file from server using FTP, the Java code works if the file is available in remote server but if the specific file is not available in the remote server a new file is getting created with same file name in local. How can I avoid this?
and I'm trying to check the properties such as last modified time, file created time etc.., of the specific file before download, I used MLST but getting type casting issues..!!
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
public class FTPDownloadFileDemo {
public static void main(String[] args) {
String server = "www.myserver.com";
int port = 21;
String user = "user";
String pass = "pass";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// APPROACH #1: using retrieveFile(String, OutputStream)
String remoteFile1 = "/test/video.mp4";
File downloadFile1 = new File("D:/Downloads/video.mp4");
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
if (success) {
System.out.println("File #1 has been downloaded successfully.");
}
outputStream2.close();
inputStream.close();
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
The retrieveFile() method always writes a local file, whether or not the remote file exists. Instead, you can use retrieveFileStream() and check the reply code.
A handy list of FTP reply codes is available from Wikipedia. If 550 is received, it means the file does not exist.
Finally, you need to use completePendingCommand() to complete the transaction and a FileOutputStream to write the file.
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile1);
int returnCode = ftpClient.getReplyCode();
if (inputStream == null || returnCode == 550) {
System.out.println("Remote file does not exist");
} else {
ftpClient.completePendingCommand();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream outputStream = new FileOutputStream(downloadFile1);
outputStream.write(buffer);
outputStream.close();
}
Your problem is that your Outputstream automatically creates the File, even if the stream is empty.
I would recommend you check first if the file exists on the server and based on that you don't even create the outputStream:
boolean checkFileExists(String filePath) throws IOException {
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile1);
returnCode = ftpClient.getReplyCode();
return inputStream == null || returnCode == 550;
}

Removing redundant code from http server, filehandler

I have set up my webserver, for the time being only localhost, at port 8080 for testing.
public class WebServer {
static int port = 8080; //not the final port
static String ip = "127.0.0.1"; // not the final IP
public static void main(String[] args) throws IOException {
InetSocketAddress i = new InetSocketAddress(ip, port); //localhost - 127.0.0.1
HttpServer server = HttpServer.create(i, 0);
server.createContext("/tester", new testHandler("index.html"));
server.createContext("/startpage", new PagesHandler());
server.createContext("/online", new OnlineHandler());
server.createContext("/logfile", new LogFileHandler());
server.setExecutor(null);
server.start();
}
I have a seperate handler for each of the page references, which basicly does the same thing.
Example for the PagesHandler()
static class PagesHandler implements HttpHandler {
String content = "public/";
#Override
public void handle(HttpExchange he) throws IOException {
File file = new File(content + "index.html");
byte[] bytesToSend = new byte[(int) file.length()];
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
bis.read(bytesToSend, 0, bytesToSend.length);
} catch (IOException ie) {
ie.printStackTrace();
}
he.sendResponseHeaders(200, bytesToSend.length);
try (OutputStream os = he.getResponseBody()) {
os.write(bytesToSend, 0, bytesToSend.length);
}
}
}
This makes me have a lot of redundant code, which i really dont see the need for.
My question is. I am guessing there is a way to parse the handler with a filename, instead of the hardcodeded filename in File file,
But how would i go about doing that?
would a constructor of the handler with a String parameter for the filename do?
like so
public pagesHandler(String fileName){
}
and in the main something like this:
server.createContext("/tester", new testHandler("index.html"));
And if not how would i go about reducing the rudandant code ?

How to make continuous interaction from client to server in Java socket programming

How to make continuous interaction from client to server in Java socket programming. Here in my program i have many folders in a directory ie) F://read and i am transferring folders with files from client to server. when at first request, one folder is transferred to the server from client and when it comes again to the client to send an another folder it's keep saying exception, java.net.SocketException: Socket is closed in the write() method of ClientProgram where i call socket.getOutputStream(). So please tell me how to resolve this problem. I think i want to use thread for each transmission, so please tell where i have to use to run this fine. Very much thank's.
Client code:
At each time forward method and write method passing data's from client to server. and listf(String directoryName) method running recursively for files and folders, when it finds folder it call's forward()and write() method. the forward() is to pass the directory path of the particular folder and write() method is to write all files here in client and passes to server at each time by the listf(String directoryName). at first time this method running fine. when at the second time again it calls write() mothod, there its giving java.net.SocketException: Socket is closed.why its happening.
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ClientProgram extends HttpServlet {
private static final long serialVersionUID = 1L;
public ClientProgram() {
super();
}
Socket socket;
ClientProgram clientProgram;
String hostDomain = "192.168.1.19";
int port = 5855;
BufferedOutputStream bos;
DataOutputStream dos;
BufferedInputStream bis;
FileInputStream fis;
PrintStream pr;
BufferedReader gt;
List<File> resultList;
public static listf(String directoryName) throws IOException {
try {
File directory = new File(directoryName);
resultList = new ArrayList<File>();
// get all the files from a directory
File[] fList = directory.listFiles();
resultList.addAll(Arrays.asList(fList));
for (File file : fList) {
if (file.isFile()) {
System.out.println("file: " + file.getAbsolutePath());
} else if (file.isDirectory()) {
String pathtomake = file.getAbsolutePath();
System.out.println("folder now: " + pathtomake);
forward(pathtomake);
write(pathtomake);
System.out.println("folder: " + file.getAbsolutePath());
listf(file.getAbsolutePath());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
bis.close();
}
if (dos != null) {
dos.close();
}
if (fis != null) {
fis.close();
}
}
return resultList;
}
public void write(String rec) throws IOException {
try {
System.out.println("rr");
bos = new BufferedOutputStream(socket.getOutputStream());
dos = new DataOutputStream(bos);
File file1 = new File(rec);
File[] fil_Files_list = file1.listFiles();
dos.writeInt(fil_Files_list.length);
System.out.println("file will ..");
for (File file : fil_Files_list) {
long length = file.length();
dos.writeLong(length);
String name = file.getName();
dos.writeUTF(name);
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
System.out.println("writin..");
int theByte = 0;
while ((theByte = bis.read()) != -1) {
bos.write(theByte);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
public void forward(String drc) throws UnknownHostException, IOException {
boolean b = socket.isConnected();
System.out.println("Socket Is active or not: " + b);
pr = new PrintStream(socket.getOutputStream());
pr.println(drc);
gt = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String tm = gt.readLine();
System.out.print(tm);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
socket = new Socket(hostDomain, port);
String directory = "F://read";
listf(directory);
}
}
Server Code:
This is my server code accept to receive folders with files. here i am receiving folder path using BufferedReader from client method called forward() and adding to the detination path ie)d://save. after that i am writing all the files to the particular folder from client method called write().
import java.io.*;
import java.net.*;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServerProgram extends HttpServlet {
private static final long serialVersionUID = 1L;
public ServerProgram() {
super();
// TODO Auto-generated constructor stub
}
BufferedReader ed;
PrintStream pr;
BufferedInputStream bis;
DataInputStream dis;
FileOutputStream fos;
BufferedOutputStream bos;
Socket socket;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
System.out.println(1);
ServerSocket serverSocket = new ServerSocket(5792);
System.out.println(2);
socket = serverSocket.accept();
ed = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String tmp = ed.readLine();
System.out.print("I Recieved :" + tmp);
pr = new PrintStream(socket.getOutputStream());
String str = "Yup I got it !!";
pr.println(str);
int g = tmp.indexOf("\\");
String di = tmp.substring(g);
String dirPath = "D://save//" + di;
System.out.println(dirPath);
File file = new File(dirPath);
JavaHeapMemory();
if (file.exists() || file.mkdirs()) {
bis = new BufferedInputStream(socket.getInputStream());
dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for (int i = 0; i < filesCount; i++) {
long fileLength = dis.readLong();
String fileName = dis.readUTF();
System.out.println("name of the file: " + fileName);
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
for (int j = 0; j < fileLength; j++) {
bos.write(bis.read());
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
bos.close();
}
if (dis != null) {
dis.close();
}
try {
socket.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
public void JavaHeapMemory() {
long heapSize = Runtime.getRuntime().totalMemory();
System.out.println("Heap Size = " + heapSize);
}
}
Exception:
java.net.SocketException: Socket is closed
at java.net.Socket.getOutputStream(Unknown Source)
at pack.ClientProgram.forward()
In this above client program i used to transfer folders to the server recursively. but its not running in continuously from client to server.so please tell me the way to do this. i am very much thankful.
You canot mix text and binary without the likelihood of confusion.
ed = new BufferedReader(new InputStreamReader(socket.getInputStream()));
This means the BufferedReader can read as much data as it likes, not just how much you ask for.
bis = new BufferedInputStream(socket.getInputStream());
This will start reading binary at some random point that the BufferedReader didn't read (not the amount you asked for)
In short, only use binary or text for a stream unless you really know what you are doing.
Your program has
while ((theByte = bis.read()) != -1)
bos.write(theByte);
This means, read until the end of the stream. It also means it will read all data sent until the connection is closed.
If you want to send multiple files in the same stream, you need another way for the receiver to know when the file ended. The simplest approach is to send the file size first, and have the reciever only read that much data.
BTW reading one byte at a time is very slow. I suggest you read into a byte[] of say size 4KB.

Problems when sending XML data from HTTP Java client to a servlet with HttpURLConnection

I have standalone java client sending xml data to http servlet using httpURLconnection class.but data appearing in non printable character format.
For simulation i have been trying to send simple string but still it was appearing in non printable format.
I have written the following client code to communicate with servlet,
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
public class HttpClient implements IClient {
private static IClient client = null;
private HttpURLConnection httpConn = null;
private OutputStream output = null;
private InputStream input = null;
private OutputStreamWriter out = null;
private HttpClient() {
}
public static IClient getHttpClient() {
if (client == null) {
client = new HttpClient();
}
return client;
}
#Override
public void connect(String urlString) throws IOException {
URL url = new URL(urlString);
httpConn = (HttpURLConnection) url.openConnection();
initConnection();
httpConn.connect();
output = httpConn.getOutputStream();
input = httpConn.getInputStream();
System.out.println("Connection Response:" + httpConn.getResponseCode());
}
#Override
public void sendFile(File file) throws IOException {
// BufferedOutputStream bos = new BufferedOutputStream(output);
// InputStream fis = new FileInputStream(file);
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
// bos.write(buffer, 0, bytesRead);
// System.out.println("write:"+buffer);
// }
// bos.close();
// fis.close();
OutputStreamWriter out = new OutputStreamWriter(output, "UTF-16");
out.write("test me");
}
#Override
public boolean isConnected() {
return httpConn != null ? true : false;
}
#Override
public void close() {
httpConn.disconnect();
}
private void initConnection() throws ProtocolException {
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
httpConn.setUseCaches(false);
httpConn.setRequestProperty("Content-Type",
"text/xml; charset=\"UTF-16\"");
httpConn.setRequestProperty("Connection", "Keep-Alive");
}
private static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
System.out.println("\nDEBUG: FileInputStream is " + file);
// Get the size of the file
long length = file.length();
System.out.println("DEBUG: Length of " + file + " is " + length + "\n");
/*
* You cannot create an array using a long type. It needs to be an int
* type. Before converting to an int type, check to ensure that file is
* not loarger than Integer.MAX_VALUE;
*/
if (length > Integer.MAX_VALUE) {
System.out.println("File is too large to process");
return null;
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while ((offset < bytes.length)
&& ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
return bytes;
}
}
and servlet code is given below,
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class XMLServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("=========inside doPost=========");
// BufferedInputStream bis = new BufferedInputStream(req.getInputStream());
// OutputStream fos = new FileOutputStream("test.xml");
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
// System.out.println("read:"+buffer);
// fos.write(buffer, 0, bytesRead);
// }
// fos.close();
// bis.close();
//
req.setCharacterEncoding("UTF-16");
InputStreamReader isr = new InputStreamReader(req.getInputStream(),"UTF-16");
char[] data = new char[10];
isr.read(data);
System.out.println(data);
for (char c : data) {
System.out.println(c);
}
}
}
Please any help me to get out of this problem.
I think you are overcomplicating it. I JUST wrote something similar that takes any file and transfers it through HTTP to a servlet. Just remember: All data is binary (including a text file)-- period. It's up to the given application to interpret that binary data. For example, notepad.exe simply reads a binary set of data and attempts to format it using ASCII standard. So knowing that, simply read a file using a raw stream, set the mime-type of the connection to application/octet-stream and send it via "PUT" method. The servlet code should be reading the file using the raw InputStream from the request and creating the corresponding file in its space.
From the client code:
URL url = new URL(urlString);
HttpURLConnection cnx = (HttpURLConnection)url.openConnection();
cnx.setRequestMethod("PUT");
cnx.setRequestProperty("Content-Type", "application/octet-stream");
// optional request property
cnx.setRequestProperty("filename", filename);
cnx.setDoOutput(true);
cnx.connect();
BufferedInputStream fileIn =
new BufferedInputStream(new FileInputStream(fileName), BUFFER_SIZE);
BufferedOutputStream out =
new BufferedOutputStream(cnx.getOutputStream(), BUFFER_SIZE);
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = fileIn.read(bytes)) != -1){
out.write(bytes, 0, bytesRead);
}
That's it.
Now the servlet code....
public void doPut(HttpServletRequest request, HttpServletResponse response){
String filename = (String)request.getHeader("filename");
StringBuilder fullPath = new StringBuilder(100);
ServletContext ctxt = getServletContext();
fullPath.append(ctxt.getRealPath(""))
.append("uploads\\").append(filename);
File f = new File(fullPath.toString());
f.createNewFile();
InputStream in = request.getInputStream();
BufferedOutputStream fileOut =
new BufferedOutputStream(new FileOutputStream(f));
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
fileOut.write(bytes, 0, bytesRead);
}
fileOut.flush();
fileOut.close();
response.setStatus(HttpServletResponse.SC_CREATED);
}
There are two major ways to upload a file on to server using http methods:
Upload a file using PUT method. This allow you to put one file at a time on to server. PUT method is easy to implement but you cannot upload a file from a html form (e.g. uploading form in your web browser) using PUT method.
Upload files using POST method. This is more complicated but most web site uses this to upload files on to server. You can do multiple file uploading per request. This is what I am going to talk about.
Note: GET is not used for file uploading unless you encode it somehow.
Uploading files using URLConnection is not straight forwards and requires you to prepare your data in "multipart form". Of course, you shouldn't do it yourself. There are a number of libraries to deal with this for you, e.g. HttpClient. If you really want to use URLConnection, I shall refer to previous question on "How to use java.net.URLConnection to fire and handle HTTP requests"
Below is the code for uploading your file using HttpClient. It is simplified from HttpClient example code.
import java.io.File;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
public class MultipartFileUploadApp {
public static void main(String[] args) {
String targetURL = "http://localhost:8080/yourserver/upload";
File targetFile = new File("/path/to/your/file.txt");
PostMethod filePost = new PostMethod(targetURL);
filePost.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
try {
System.out.println("Uploading " + targetFile.getName() + " to " + targetURL);
// add more parts you want to upload multiple files.
Part[] parts = {new FilePart(targetFile.getName(), targetFile)};
filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
int status = client.executeMethod(filePost);
if (status == HttpStatus.SC_OK) {
System.out.println("Upload complete, response=" + filePost.getResponseBodyAsString());
} else {
System.out.println("Upload failed, response=" + HttpStatus.getStatusText(status));
}
} catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
filePost.releaseConnection();
}
}
}
For the server side, you have to parse multipart form request. Of course, there exists libraries to do that for you. Here is the snipplet I am using
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class CommonsFileUploadServlet extends HttpServlet {
private static final String TMP_DIR_PATH = "c:\\tmp";
private File tmpDir;
private static final String DESTINATION_DIR_PATH = "c:\\tmp\\files";
private File destinationDir;
public void init(ServletConfig config) throws ServletException {
super.init(config);
tmpDir = new File(TMP_DIR_PATH);
if (!tmpDir.isDirectory()) {
throw new ServletException(TMP_DIR_PATH + " is not a directory");
}
//String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
destinationDir = new File(DESTINATION_DIR_PATH);
if (!destinationDir.isDirectory()) {
throw new ServletException(DESTINATION_DIR_PATH + " is not a directory");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
out.println("<h1>Servlet File Upload Example using Commons File Upload</h1>");
out.println();
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
/*
*Set the size threshold, above which content will be stored on disk.
*/
fileItemFactory.setSizeThreshold(1 * 1024 * 1024); //1 MB
/*
* Set the temporary directory to store the uploaded files of size above threshold.
*/
fileItemFactory.setRepository(tmpDir);
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
try {
/*
* Parse the request
*/
List items = uploadHandler.parseRequest(request);
out.println("Count : " + items.size());
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
/*
* Handle Form Fields.
*/
if (item.isFormField()) {
out.println("Field = " + item.getFieldName() + ", Value = " + item.getString());
} else {
//Handle Uploaded files.
out.println("Field Name = " + item.getFieldName()
+ ", File Name = " + item.getName()
+ ", Content type = " + item.getContentType()
+ ", File Size = " + item.getSize());
/*
* Write file to the ultimate location.
*/
File file = new File(destinationDir, item.getName());
item.write(file);
}
}
out.close();
} catch (FileUploadException ex) {
log("Error encountered while parsing the request", ex);
} catch (Exception ex) {
log("Error encountered while uploading file", ex);
}
}
}
I have standalone java client sending xml data to http servlet using httpURLconnection class.but data appearing in non printable character format.
I can understand that. You're sending the data as UTF-16, but the XML file itself is likely not saved in UTF-16. You need to use the same character encoding as the XML file is saved in. That's usually UTF-8.
For simulation i have been trying to send simple string but still it was appearing in non printable format.
I don't understand that. It should work fine the way as you have in the code. Probably you didn't test it properly.

Categories