I'm trying to build a simple HTTP Server using Java, using
java.net.ServerSocket = new ServerSocket(this.port, 0, this.ip);
java.net.Socket connection = null;
connection = server.accept();
java.io.OutputStream out = new BufferedOutputStream(connection.getOutputStream());
when connected using web browser, i'm simply write the output (HTTP headers + html code) from a string
String headers = "http headers";
String response = "this is the response";
out.write(headers.getBytes());
out.write(response.getBytes());
out.flush();
connection.close();
and the browser display it correctly.
And now my problem is, i want to construct a full webpage (html, javascript, css, images) and put those files into the Java package (JAR) file, and of course, those files are designed not-to-be modified after the JAR is ready to use. And here's the questions:
how to achieve this? storing the files inside the JAR and then output them when a connection is made.
how output images file (non-text) just like output-ing String by out.write() ?
Thanks, any sample or code is appreciated.
Is implementing an HTTP server your primary problem or just a way to achieve some other goal? If the latter, consider embedding Tomcat or Jetty, much simpler and with standard servlet API.
Back to your question: JAR is just a ZIP file, you can put anything there, including files, images, movies, etc. If you place a file inside a JAR file you can load it easily with:
InputStream is = getClass().getResourceAsStream("/dir/file.png");
See these questions for details how getResourceAsStream() works:
Junit + getResourceAsStream Returning Null
getResourceAsStream() vs FileInputStream
how do you make getResourceAsStream work while debugging Java in Eclipse?
Different ways of loading a file as an InputStream
getResourceAsStream() is always returning null
About your second question: when you have an InputStream instance you can just read it byte-by-byte and copy to target out OutputStream. Of course there are better, safer and faster ways, but that's beyond the scope of this question. Just have a look at IOUtils.copy():
IOUtils.copy(is, out);
And the last hint concerning your code: if you are sending Strings , consider OutputStreamWriter and PrintWriter which have easier API.
To work with JAR files use JarOutputStream or ZipOutputStream. To output binary data just do not wrap your output stream with Writer. OuputStream knows to write bytes using method write(byte) and write(byte[]).
The only question here is "Why are you developing HTTP server yourself?"
As long as it is not a housework I would not try to reinvent the wheel and develop another web server. There a small embedded Java web-servers available which can be used for that purpose.
I have for example use the Tiny Java Web Server and Servlet Container several times.
If you have integrated it into your application you can implement a new javax.servlet.http.HttpServlet that reads the files from the resources of your JAR file. The content can be loaded as Tomasz Nurkiewicz already pointed out getClass().getRourceAsStream(...).
Related
I'm using Play Framework 2.0.3 to create an application which delivers Excel files that should be downloadable by the user.
response().setContentType("application/x-download");
response().setHeader("Content-disposition","attachment; filename=tradeLogTest.xlsx");
but,how to get the outputstream from response()?tks
Play's action can return a File:
response().setContentType("application/x-download");
response().setHeader("Content-disposition","attachment; filename=tradeLogTest.xlsx");
return ok(new File("/absolute/path/to/tradeLogTest.xlsx"));
Here's an API for Results
Providing download option for static files can be done in Play as:
Ok.sendFile(new File("path to file/abc.csv"), inline=true).withHeaders(CACHE_CONTROL->"max-age=3600",CONTENT_DISPOSITION->"attachment; filename=abc.csv", CONTENT_TYPE->"application/x-download");
There are other parameters that are also available
For Internet Explorer - make sure you set the Content Disposition
Serving files
If it’s not a problem to load the whole content into memory for simple content what about a large data set? Let’s say we want to send back a large file to the web client.
read more at : http://www.playframework.com/documentation/2.0.x/JavaStream
I'm trying to expand on the functionality here:
https://github.com/netty/netty/tree/3/src/main/java/org/jboss/netty/example/http/file
By providing support to stream URLs instead of Files as the content I'd like to serve is in the classpath within my JAR. Unfortunately I can't seem to figure out a good way to stream a URL or InputStream with Jetty, nor can I find any examples.
Examples or reference to JavaDoc would be appreciated to help get me on the right path.
Just use ChunkedWriteHandler and write an ChunkedStream that wraps the InputStream.
This should work out quite all..
This question already has answers here:
How to save uploaded file in JSF
(2 answers)
Closed 7 years ago.
Here with another question on Images ( which seems to be more difficult than I initialy predicted) I'm working on a java Web app with JSF 2.0 ( apache myFaces) and I want this app to be able to upload a picture to a destination on the server it's going to run on. I have a Windows r2 2008 Server running a mySQL Db, but I don't want to store the image in the db, I'd rather store it somewhere in the server and then just save the path as a string in the db.
I was told this is the best way, but I can't seem to find an example on how to save it on the server. I run the app on the Apache tomcat Server as a WAR file. so I don't know if I have to save the file to a path on the server drive (i.e. C:\images) or a special folder in the project itself ( within the java, html files) any help at all is greatly appreciated. I'm totally lost and have been stuck the whole day trying to figure this out.
The code I use to upload the image to the java class is this ( courtesy of CodyS):
InputStream is = uploadedFile.getInputStream();
byte[] buffer = new byte[(int) uploadedFile.getSize()];
is.read(buffer);
File f = new File("C:\\temp\\" + this.patient.getPk() + ".jpeg");
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer); //This is where I write it to the C Drive
fos.close();
is.close();
instead of writing it to my C drive I'm going to run it on the server, but where should I store the image to later retriev and display in an xhtml file? I hope I'm being clear on what I need, let me know if I am not and I'll try to explain in another way.
instead of writing it to my C drive I'm going to run it on the server, but where should I store the image to later retriev and display in an xhtml file?
That depends on how much control you have over configuring the server. Ideal would be to configure a fixed path outside the Tomcat webapps folder. For example, /var/webapp/upload. You can set this path as a VM argument or environment variable so that your webapp can retrieve it programmatically without the need to change the code.
For example, when specifying as VM argument -Dupload.location=/var/webapp/upload, you can complete the upload as follows:
Path folder = Paths.get(System.getProperty("upload.location"));
String filename = FilenameUtils.getBaseName(uploadedFile.getName());
String extension = FilenameUtils.getExtension(uploadedFile.getName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}
String uploadedFileName = file.getFileName().toString();
// Now store it in DB.
As to serving the file back, most ideal would be to add the upload location as a separate <Context> to Tomcat. E.g.
<Context docBase="/var/webapp/upload" path="/uploads" />
This way you can access it directly by http://example.com/uploads/foo-123456.ext
If you have zero control over configuring the server, then, well, storing in the DB or sending to a 3rd party host such as Amazon S3 is your best bet.
See also:
How to provide relative path in File class to upload any file?
Reliable data serving
I would consider allowing the user to upload to Amazon S3 directly. Amazon offers a service for that. Using that service, the client would post a form with the file directly to S3. Once the file has arrived there, Amazon will redirect the client to one of your endpoints, to confirm that the data has arrived, passing you the relevant details.
The benefits are:
Your server does not spend a lot of time in receiving huge files. You can spend your CPU cycles on something a little bit more interesting.
The availability guaranteed by storing it on S3 is probably better then what you would get by storing it on your own Windows box.
It scales. At some point, your filesystem will run out of space. (Or you reach the limit of what you can store inside a folder.)
I'd suggest that you save your images in a subfolder which is in your application's WEB-INF folder. Remember that when you use Tomcat, your WAR files will be extracted automatically. This approach also has the advantage that you can always migrate your application to another server, you only have to save the path relative to WEB-INF folder in your DB.
I'm currently using commons-net library for FTP client in my app. I have to download from remote server some files, by some criteria based on the file name. This is a very simplified and reduced version of my actual code (because I do some checks and catch all possible exceptions), but the essence is there:
//ftp is FTPClient object
//...
files = ftp.listFiles();
for (FTPFile ftpFile : files) {
String name = ftpFile.getName();
if(conformsCriteria(name)) {
String path = outDirectory + File.separatorChar + name;
os = new FileOutputStream(path);
ftp.retrieveFile(name, os);
}
}
Now, what I noticed is that when I run this code, wait a few seconds, and then plug out network cable, output directory contains some "empty" files plus the files actually downloaded, which leads me to believe that this method is working somewhat asynchronously... But then again, some files are downloaded (size > 0KB), and there are these empty files (size = 0KB), which leads me to believe that it is still serialized download... Also, function retrieveFile() returns, I quote documentation:
True if successfully completetd, false if not
What I need is serialized download, because I need to log every unsuccessful download.
What I saw browsing through the commons-net source is that, if I'm not wrong, new Socket is created for each retrieveFile() call.
I'm pretty confused about this, so If someone could explain what is actually happening, and offer solution with this library, or recommend some other FTP java library that supports blocking download per file, that would be nice.
Thanks.
You could just use the java.net.URLConnection class that has been present forever. It should know how to handle FTP URLs just fine. Here is a simple example that should give the blocking behavior that you are looking for.
The caveat is that you have to manage the input/output streams yourself, but this should be pretty simple.
Ok, to briefly answer this in order not to confuse people who might see this question.
Yes, commons-net for FTP is working as I thought it would, that is, retrieveFile() method blocks until it's finished with the download.
It was (of course) my own "mistake" in the code that let me think otherwise.
I am getting a a InputStream from getResourceAsStream(), and I managed to read from the file by passing the returned InputStream to a BufferedReader.
Is there any way I can write to the file as well?
Not directly, no - getResourceAsStream() is intended to return a view on read-only resources.
If you know that the resource is a writeable file, though, you can jump through some hoops, e.g.
URL resourceUrl = getClass().getResource(path);
File file = new File(resourceUrl.toURI());
OutputStream output = new FileOutputStream(file);
This should work nicely on unix-style systems, but windows file paths might give this indigestion. Try it and find out, though, you might be OK.
Is there any way I can write to the
file as well?
Who says it's a file? The whole point of getResourceAsStream() is to abstract that away because it might well not be true. Specifically, the resource may be situated in a JAR file, may be read from a HTTP server, or really anything that the implementer of the ClassLoader could imagine.
You really shouldn't want to write to a resource that's part of your program distribution. It's conceptually the wrong thing to do in most cases. Settings or User-specific data should go to the Preferences API or the user's home directory.