Servlet java, server side, send a string as a new txt file - java

I have a Java web app. The user is able to upload a file (via POST request), and then the servlet will execute some code on this file. The output of this code is a string.
How to return a file to the user, without create one on the server side? Is that possible?

yes,
you have to set content disposition header then write the stream to response.

Try to use that code
package com.hainasoft.web;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends javax.servlet.http.HttpServlet implements
javax.servlet.Servlet {
static final long serialVersionUID = 1L;
private static final int BUFSIZE = 4096;
private String filePath;
public void init() {
// the file data.xls is under web application folder
filePath = getServletContext().getRealPath("") + File.separator + "data.xls";
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
File file = new File(filePath);
int length = 0;
ServletOutputStream outStream = response.getOutputStream();
ServletContext context = getServletConfig().getServletContext();
String mimetype = context.getMimeType(filePath);
// sets response content type
if (mimetype == null) {
mimetype = "application/octet-stream";
}
response.setContentType(mimetype);
response.setContentLength((int)file.length());
String fileName = (new File(filePath)).getName();
// sets HTTP header
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
byte[] byteBuffer = new byte[BUFSIZE];
DataInputStream in = new DataInputStream(new FileInputStream(file));
// reads the file's bytes and writes them to the response stream
while ((in != null) && ((length = in.read(byteBuffer)) != -1))
{
outStream.write(byteBuffer,0,length);
}
in.close();
outStream.close();
}
}
it is important to set the myme type
mimetype = "application/octet-stream";
and with this you set a download dialog to the user
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
I have retrieved all that information from
http://www.java-forums.org/blogs/servlet/668-how-write-servlet-sends-file-user-download.html
so take a look in it for more accurate information.

Related

Uploading file with jetty and servlet

I am writing a java application to upload a file from browser. I am using jetty 9.4.15 and java servlet. When I upload the file, I get the below error message.
java.lang.IllegalStateException: No multipart config for servlet
at org.eclipse.jetty.server.Request.getParts(Request.java:2342)
at org.eclipse.jetty.server.Request.getParts(Request.java:2330)
at org.eclipse.jetty.server.Request.getPart(Request.java:2318)
at com.RekognizeServlet.doPost(RekognizeServlet.java:47)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:873)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:205)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:502)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:132)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:745)
Below is the code I have written
SimplestServer.java
package com;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
public class SimplestServer
{
public static void main(String[] args) throws Exception
{
Server server = new Server(8080);
ServletHandler handler = new ServletHandler();
server.setHandler(handler);
handler.addServletWithMapping(RekognizeServlet.class, "/tryAndRecognize");
server.start();
server.join();
}
}
RekognizeServlet.java
package com;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
#MultipartConfig
public class RekognizeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public RekognizeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<!DOCTYPE html><html lang=\"en\"><head><title>File Upload</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head><body><form method=\"POST\" action=\"tryAndRecognize\" enctype=\"multipart/form-data\" >File:<input type=\"file\" name=\"file\" id=\"file\" /> <br/></br><input type=\"submit\" value=\"Upload\" name=\"upload\" id=\"upload\" /></form></body></html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// Create path components to save the file
final String path = "/path/";
final Part filePart = request.getPart("file");
final Collection<Part> fileParts = request.getParts();
final String fileName = getFileName(filePart);
OutputStream out = null;
InputStream filecontent = null;
final PrintWriter writer = response.getWriter();
try {
out = new FileOutputStream(new File(path + File.separator + fileName));
filecontent = filePart.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = filecontent.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
System.out.println("File being uploaded to {1}");
} catch (FileNotFoundException fne) {
writer.println("You either did not specify a file to upload or are "
+ "trying to upload a file to a protected or nonexistent " + "location.");
writer.println("<br/> ERROR: " + fne.getMessage());
System.out.println("Problems during file upload");
fne.printStackTrace();
} finally {
if (out != null) {
out.close();
}
if (filecontent != null) {
filecontent.close();
}
if (writer != null) {
writer.close();
}
}
}
private String getFileName(final Part part) {
final String partHeader = part.getHeader("content-disposition");
System.out.println("Part Header = " + partHeader);
for (String content : part.getHeader("content-disposition").split(";")) {
if (content.trim().startsWith("filename")) {
return content.substring(content.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
}
I am not using Handler like many examples online. Can anyone help?
Below are the links I have seen (not all)
How to implement FileUpload in embedded Jetty?
https://github.com/eclipse/jetty.project/issues/240
Since you are using Embedded Jetty the bytecode scanning for annotations (such as #MultipartConfig) isn't enabled by default.
Enabling the bytecode scanning requires a lot of effort, it's actually easier to just specify in code what the annotations would actually do.
So, in your case, all you need to change is the initialization of your servlet.
Example:
Server server = new Server(8080);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
ServletHolder uploadHolder = context.addServlet(RekognizeServlet.class,
"/tryAndRecognize");
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
File locationDir = new File(tmpDir, "jetty-fileupload");
if (!locationDir.exists()) locationDir.mkdirs();
String location = locationDir.getAbsolutePath();
long maxFileSize = 1024 * 1024 * 50;
long maxRequestSize = -1L;
int fileSizeThreshold = 1024 * 1024;
MultipartConfigElement multipartConfig = new MultipartConfigElement(location,
maxFileSize, maxRequestSize, fileSizeThreshold);
uploadHolder.getRegistration().setMultipartConfig(multipartConfig);
server.setHandler(context);
server.start();
It's important to note that MultipartConfig needs at a location specified (as a bare minimum).
Also, MultipartConfig will not work without a ServletContext, which the ServletContextHandler gives you.

C# file upload to Java EE server

My problem is, that after uploading the content of file is [object Object].
How can I upload a file properly?
Server:
package com.turbulence6th.servlets;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
#WebServlet("/saveFile")
#MultipartConfig
public class SaveFile extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String webAppPath = getServletContext().getRealPath("/");
Part file = request.getPart("file");
String filename = getFileName(file);
InputStream is = file.getInputStream();
String directoryPath = webAppPath + File.separator + "files";
File directory = new File(directoryPath);
if(!directory.exists()){
directory.mkdir();
}
String filePath = directoryPath + File.separator + filename;
FileOutputStream fos = new FileOutputStream(filePath);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = is.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
fos.close();
}
private String getFileName(Part part) {
for (String content : part.getHeader("content-disposition").split(";")) {
if (content.trim().startsWith("filename")) {
return content.substring(
content.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
}
Client:
using (var wb = new WebClient())
{
wb.UploadFile("http://" + host + ":8080/saveFile", "POST", path);
}
I don't see any manipulations with response. Inside doPost you copy file content to the request. Is it what you want?
By the way - I don't see any reason to not use copy().

How to properly upload (image) file to Google Cloud Storage using Java App Engine?

I have a Google app engine instance, using java (sdk 1.9.7), and it is connected to Google Cloud Storage. I'm able to successfully take a request's input and output it to a file/object in my google cloud storage bucket. here's my code for my servlet:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// read the input stream
byte[] buffer = new byte[1024];
List<byte[]> allBytes = new LinkedList<byte[]>();
InputStream reader = req.getInputStream();
while(true) {
int bytesRead = reader.read(buffer);
if (bytesRead == -1) {
break; // have a break up with the loop.
} else if (bytesRead < 1024) {
byte[] temp = Arrays.copyOf(buffer, bytesRead);
allBytes.add(temp);
} else {
allBytes.add(buffer);
}
}
// init the bucket access
GcsService gcsService = GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
GcsFilename filename = new GcsFilename("my-bucket", "my-file");
Builder fileOptionsBuilder = new GcsFileOptions.Builder();
fileOptionsBuilder.mimeType("text/html"); // or "image/jpeg" for image files
GcsFileOptions fileOptions = fileOptionsBuilder.build();
GcsOutputChannel outputChannel = gcsService.createOrReplace(filename, fileOptions);
// write file out
BufferedOutputStream outStream = new BufferedOutputStream(Channels.newOutputStream(outputChannel));
for (byte[] b : allBytes) {
outStream.write(b);
}
outStream.close();
outputChannel.close();
}
and when i do something like a curl POST command, this works perfectly if i just feed it data directly, like so:
curl --data "someContentToBeRead" http://myAppEngineProj.appspot.com/myServlet
and i can see the exactly string that i put in, "someContentToBeRead".
HOWEVER, when i put a file, like so:
curl -F file=#"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
the file is completely corrupted. if i upload a text file, it has a line of crap in the beginning of the file, and a line of crap at the end, like:
------------------------------266cb0e18eba
Content-Disposition: form-data; name="file"; filename="blah.txt"
Content-Type: text/plain
hi how are you
------------------------------266cb0e18eba--
how do i tell cloud storage i want to store the data as file?
This is what worked for me
To upload, use
curl -F file=#"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
And the servlet looks like
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.channels.Channels;
import java.util.Enumeration;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.google.appengine.tools.cloudstorage.GcsFileOptions;
import com.google.appengine.tools.cloudstorage.GcsFilename;
import com.google.appengine.tools.cloudstorage.GcsOutputChannel;
import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.appengine.tools.cloudstorage.RetryParams;
public class UploadServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(UploadServlet.class.getName());
private final GcsService gcsService = GcsServiceFactory.createGcsService(new RetryParams.Builder()
.initialRetryDelayMillis(10)
.retryMaxAttempts(10)
.totalRetryPeriodMillis(15000)
.build());
private String bucketName = "myBucketNameOnGoogleCloudStorage";
/**Used below to determine the size of chucks to read in. Should be > 1kb and < 10MB */
private static final int BUFFER_SIZE = 2 * 1024 * 1024;
#SuppressWarnings("unchecked")
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String sctype = null, sfieldname, sname = null;
ServletFileUpload upload;
FileItemIterator iterator;
FileItemStream item;
InputStream stream = null;
try {
upload = new ServletFileUpload();
res.setContentType("text/plain");
iterator = upload.getItemIterator(req);
while (iterator.hasNext()) {
item = iterator.next();
stream = item.openStream();
if (item.isFormField()) {
log.warning("Got a form field: " + item.getFieldName());
} else {
log.warning("Got an uploaded file: " + item.getFieldName() +
", name = " + item.getName());
sfieldname = item.getFieldName();
sname = item.getName();
sctype = item.getContentType();
GcsFilename gcsfileName = new GcsFilename(bucketName, sname);
GcsFileOptions options = new GcsFileOptions.Builder()
.acl("public-read").mimeType(sctype).build();
GcsOutputChannel outputChannel =
gcsService.createOrReplace(gcsfileName, options);
copy(stream, Channels.newOutputStream(outputChannel));
res.sendRedirect("/");
}
}
} catch (Exception ex) {
throw new ServletException(ex);
}
}
private void copy(InputStream input, OutputStream output) throws IOException {
try {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = input.read(buffer);
while (bytesRead != -1) {
output.write(buffer, 0, bytesRead);
bytesRead = input.read(buffer);
}
} finally {
input.close();
output.close();
}
}
}
References : Wilson Yeung's answer above and This Post
Although the other post has a limitation of upload size < 32 mb,
that was not a problem for me.
And this code also handles mime types automatically.
As far as I can tell, there is no problem with Google Cloud Storage or the APIs; the problem is earlier, in the reading of the content from HttpServletRequest.
The lines containing ------266cb0e18eba are actually part of the MIME encoding and marks the beginning and end of a part.
You can resolve the issue in one of two ways.
Option A: Keep the code the same, but change the way you upload data
Replace:
$ curl -F file=#"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
With:
$ curl -X POST -d #"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
Option B: Fix the Java code and continue using curl as you are using it
Replace:
java.io.InputStream is = request.getInputStream();
With:
javax.servlet.http.Part filePart = request.getPart("file");
java.io.InputStream is = filePart.getInputStream()
Which opens an input stream on the correct part in the multipart MIME message which curl constructed.
This is documented here:
http://docs.oracle.com/javaee/6/tutorial/doc/gmhba.html
Option B is probably the better option because it will work with forms and form uploads.

Java Servlet: Pick files to download

I'm pretty new to Java Servlets/Apache Tomcat/etc but I was able to find some handy resources on how I can implement Download and Upload functionality.
When the user wants to upload a file, they click the button, and they are prompted to select a file. However, when they want to download a file, they only have the choice of just the one file (specified in the servlet).
So, my question is: Is there a way to list out the directory somehow that would let the user pick a particular file, and then download that file?
Below is my code if you need a point of reference:
NOTE: This code works, I just want to know how I can expand on it with the desired effect I want.
package testPackage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet
{
private static final String absFilePath = "/test/files/download/test.txt";
private static final String relFilePath = "/files/download/test.txt";
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//Quick switch to determine what type of path to user
boolean useAbsolute = false; //Defaults to relative
//Initialize a new File
File downloadFile = new File("");
//Check if we want to use the absolute file path
if(useAbsolute)
{
//Read the input file from the absolute path
downloadFile = new File(absFilePath);
}
//Otherwise, we are using relative
else
{
//Read the input file from the relative path
String relativePath = getServletContext().getRealPath(relFilePath);
downloadFile = new File(relativePath);
//System.out.println("Relative Path: " + relativePath);
}
//Open up the FileInputStream
FileInputStream inputStream = new FileInputStream(downloadFile);
//Obtain the Servlet Context
ServletContext context = getServletContext();
//Get the MIME type of the file
String mimeType = context.getMimeType(absFilePath);
//If we don't get a type, default to binary
if(mimeType == null)
{
//Set to binary type if the MIME mapping is not found
mimeType = "application/octet-stream";
}
//Just some logging
System.out.println("MIME Type: " + mimeType);
//Modify Servlet Response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
//Set the header key/value
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
response.setHeader(headerKey, headerValue);
//Obtain the response output stream
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
//While there are bytes to write
while((bytesRead = inputStream.read(buffer)) != -1)
{
outputStream.write(buffer, 0, bytesRead);
}
//Close the streams
inputStream.close();
outputStream.close();
}
}

How to display images from database in JSF

I have images that are stored in the database as a BLOB. Now I can display them in my jsf pages using Richfaces mediaOutput tag.
Is it possible for images to have path like "/images/image.jpg" while images are stored in the database.
While searching for an answer I came around something like this:
#GET
#Path("/files/{filename}")
#Produces(MediaType.WILDCARD)
Best regards,
Ilya Sidorovich
You could write a servlet picking up every request to /image/* or something that suits you.
And in your servlet you retrieve the correct data from your database via request parameters.
And you write out the data via
response.getOutputStream().write(content);
(content being the bytearray of you image)
Thank you roel and BalusC!
If anyone comes around this issue, here is what you can do.
package org.gicm.test;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.inject.Inject;
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import org.gicm.cms.CMSDao;
import org.gicm.model.UploadedImage;
#WebServlet("/images/*")
public class TestServlet extends HttpServlet {
#Inject
private CMSDao cms;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String imageId = String.valueOf(request.getPathInfo().substring(1)); // Gets string that goes after "/images/".
UploadedImage image = cms.findImage(imageId); // Get Image from DB.
response.setHeader("Content-Type", getServletContext().getMimeType(image.getName()));
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(image.getData()); // Creates buffered input stream.
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[8192];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
}
}

Categories