I have a main form for file uploading. A servlet is doing the upload job. All the files are with the same name structure, so I'm splitting it and getting the parameters. Then I'm placing them into a JSONArray and then I'm passing these parameters to the index page, named test.jsp in my case.
The problem Is, That I have no idea on how to create a table and fill it with the details held in the JSON.
Here my index(test.jsp) page is:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<title>File Upload Demo</title>
</head>
<body>
<center>
<form method="post" action="uploadFile" enctype="multipart/form-data">
Select file to upload:
<input type="file" name="uploadFile" multiple/>
<br/><br/>
<input type="submit" value="Upload" />
</form>
${message}
<br />
${jsonString}
</center>
</body>
</html>
I'm using ${jsonString} to check, if the JSON is passed correctly.
It looks like:
[
{
"MDName": "Angel Bankov",
"MDCode": "2288",
"month": "April",
"year": "2013",
"target/achieved": "Target"
},
{
"MDName": "Angel Bankovsky",
"MDCode": "2289",
"month": "April",
"year": "2015",
"target/achieved": "Achieved"
}
]
Here my servlet is:
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.RequestDispatcher;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* A Java servlet that handles file upload from client.
*
* #author www.codejava.net
*/
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// location to store file uploaded
private static final String UPLOAD_DIRECTORY = "upload";
// upload settings
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3;
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40;
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50;
/**
* Upon receiving file upload submission, parses the request to read
* upload data and saves the file on disk.
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// checks if the request actually contains upload file
if (!ServletFileUpload.isMultipartContent(request)) {
// if not, we stop here
PrintWriter writer = response.getWriter();
writer.println("Error: Form must has enctype=multipart/form-data.");
writer.flush();
return;
}
//JSON Declaration
JSONArray splitDetailsArray = new JSONArray();
// configures upload settings
DiskFileItemFactory factory = new DiskFileItemFactory();
// sets memory threshold - beyond which files are stored in disk
factory.setSizeThreshold(MEMORY_THRESHOLD);
// sets temporary location to store files
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
// sets maximum size of upload file
upload.setFileSizeMax(MAX_FILE_SIZE);
// sets maximum size of request (include file + form data)
upload.setSizeMax(MAX_REQUEST_SIZE);
// constructs the directory path to store upload file
// this path is relative to application's directory
String uploadPath = getServletContext().getRealPath("")
+ File.separator + UPLOAD_DIRECTORY;
// creates the directory if it does not exist
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
// parses the request's content to extract file data
#SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// iterates over form's fields
for (FileItem item : formItems) {
// processes only fields that are not form fields
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// saves the file on disk
item.write(storeFile);
request.setAttribute("message",
"Upload has been done successfully!");
}
}
File folder = new File("D:/Workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HDSHubTargetAchieved/upload");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
String[] parts = listOfFiles[i].getName().split("[_.']");
String part1 = parts[0];
String part2 = parts[1];
String part3 = parts[2];
String part4 = parts[3];
String part5 = parts[4];
// JSON
JSONObject splitDetails = new JSONObject();
splitDetails.put("MDCode", part1);
splitDetails.put("target/achieved", part2);
splitDetails.put("month", part3);
splitDetails.put("year", part4);
splitDetails.put("MDName", part5);
splitDetailsArray.put(splitDetails);
// TEST OUTPUT \\
System.out.println("Code:" + part1 + "\n Target/Achieved: " + part2 + "\n Month: " + part3 + "\n Year: " + part4 + "\n Name: " + part5);
}
}
// TEST OUTPUT \\
System.out.println(splitDetailsArray.toString());
}
} catch (Exception ex) {
request.setAttribute("message",
"There was an error: " + ex.getMessage());
}
// redirects client to message page
request.setAttribute("jsonString", splitDetailsArray.toString());
RequestDispatcher dispatcher = request.getRequestDispatcher("/test.jsp");
dispatcher.forward(request, response);
// getServletContext().getRequestDispatcher("/test.jsp").forward(
// request, response);
}
}
The above codes are running on tomcat 6
Again, I'm looking for a way to pass this JSON to a table in the test.jsp file.
In the most cases I'm asking just for an advice, but this time I will need some code examples, because I really have no idea on how to do it. It's my very first touch to the servlets. I lost 2 hours searching for help, but I was unable to find it.
Basically you would to loop through your JSON array using javascript and printing out html table tags. Here is an example answer below that should help you. I just searched for "print html tables from json" on Google.
Convert json data to a html table
Related
I have to generate pdf of HTML page. I have written a method for this but it generates an error. Please guide me where I'm wrong. Thank You!
public void htmlToPdf(
String htmlPath,
File pdfFile
) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(
document,
new FileOutputStream(pdfFile)
);
document.open();
XMLWorkerHelper.getInstance().parseXHtml(
writer,
document,
new FileInputStream(htmlPath),
Charset.forName("UTF-8")
);
document.close();
}
Error :
Cannot resolve method 'parseXHtml(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document, java.io.FileInputStream, java.nio.charset.Charset)'
So you want to generate PDFs from HTML with Java? (check EDIT 2020 at the bottom)
Here is the procedure I am using with flying-saucer.
Format your HTML with CSS 2.1
Write the process to generate a PDF
Create the PDF generator interface
Use a custom object to wrap images with attributes for further formatting
Implements your interface with your PDF parameters and images
1. Format your HTML with CSS 2.1
Example can be a JSP with ELs, any other template (you will be able to get the
generated HTML with parameters with an internal POST request), or just static
HTML.
You cannot use proportionnal values like em, rem, vh, vw or complex
CSS like animations.
You can use <style> </style> tag or inline style= attribute
Here is an example of a JSP in my webapp.
<!DOCTYPE html>
<%# page session="false"
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
isELIgnored="false" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<META CHARSET="UTF-8" />
<title>My PDF</title>
<style>
/* you can add reset css too */
/* stylesheet */
body { font-family: sans-serif; }
.someCSSClass {}
.anotherCSSClass {}
</style>
</head>
<body>
<div class="someCSSClass">
<p class="anotherCSSClass" style="line-height:16px;">
${ param.aParameter }
</p>
2. Write the process to generate a PDF with an interface
Why using an interface? Because in the case you need to generate additional
PDFs from different models you will not have to write the same logic to
generate each PDFs.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImage;
import com.itextpdf.text.pdf.PdfIndirectObject;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import main.java.bean.ImagePDF;
import main.java.interface.PDFInterface;
import main.java.bean.Constants;
/**
* PDFGenerator
* Class to generate PDF (can implement Servlet).
*/
public class PDFGenerator {
private static final String TMP_DIR = System.getProperty("java.io.tmpdir");
/*
* May not be a GET, can be simple method call for local application or
* whatever you need
*/
#Override
protected void goGet(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
PDFInterface pdfImplementation = null;
/*
* instance your PDF Model implementation according to this
* parameter (for example)
*/
int pdfModel = Integer.parseInt(
request.getParameter("requestedPDFModel")
);
switch (pdfModel) {
case Constants.PDF_MODEL_1:
pdfImplementation = new PDFImplementationOne();
/*
* You could get the image reference from GET request too,
* or from database or from constants
*/
pdfImplementation.addImage(
"image1.png",
120,
50,
"image_name1",
request
);
break;
case Constants.PDF_MODEL_2:
pdfImplementation = new PDFImplementationTwo();
pdfImplementation.addImage(
"image2.png",
350,
70,
"image_name2",
request
);
break;
default :
System.out.println("Cannot find an implementation for the requested PDF.");
return null;
}
String html = null;
/*
Get the HTML from an URL : if your implementation returns null
then you can for example decide to get the HTML from a file in your implementation
*/
if (pdfImplementation.getUrl(request) != null) {
// Send POST request to generate the HTML from a template (JSP, JSF, Thymeleaf, ...)
URLConnection connection = new URL(
pdfImplementation.getUrl(request)
+pdfImplementation.getEncodedQueryString()
).openConnection();
connection.setDoOutput(true); // POST : remove this to do a GET
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty(
"Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8"
);
try (OutputStream output = connection.getOutputStream()) {
output.write(
pdfImplementation
.getEncodedQueryString()
.getBytes(StandardCharsets.UTF_8)
);
}
// Open an input stream on the response
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream())
);
StringBuilder sb = new StringBuilder();
// A line in our generated HTML
String inputLine;
// Read all HTML lines and concatenate
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
html = sb.toString();
in.close();
}
// Get the HTML from a File
else {
html = String.join(
"",
Files.readAllLines(pdfImplementation.getHTMLFile().toPath())
);
}
// Create a temp file to make the PDF
File tempPDFFile = new File(
TMP_DIR + pdfImplementation.getGeneratedPDFFileName()
);
if (!tempPDFFile.exists()) { tempPDFFile.createNewFile(); }
FileOutputStream fos = new FileOutputStream(tempPDFFile);
// Output the HTML to the temp PDF file
new ITextRenderer() {{
setDocumentFromString(html);
layout();
createPDF(fos);
}};
fos.close();
// Create your final PDF file
File pdf = new File(pdfImplementation.getPDFFilename());
// Add images if needed
addImageToPDF(pdfImplementation, tempPDFFile, pdf);
// Write in response if you need servlet implementation
writePDFContentToResponse(pdf, response);
}
/**
* writePDFContentToResponse
* #param pdf : the final PDF file
* #param response : a HTTPServletResponse to write PDF file bytes
* #throws IOException
*/
void writePDFContentToResponse(
File pdf,
HttpServletResponse response
) throws IOException {
InputStream fis = new FileInputStream(pdf);
String mimeType = getServlet().getServletContext()
.getMimeType(pdf.getAbsolutePath());
response.setContentType(
mimeType != null ? mimeType : "application/octet-stream"
);
response.setContentLength((int) pdf.length());
response.setHeader(
"Content-Disposition",
"attachment; filename="+pdf.getName()+".pdf"
);
ServletOutputStream os = response.getOutputStream();
byte[] bufferData = new byte[1024];
int read = 0;
while((read = fis.read(bufferData)) != -1) {
os.write(bufferData, 0, read);
}
os.flush();
os.close();
fis.close();
response.flushBuffer();
Files.delete(pdf.toPath());
}
/**
* addImageToPDF
*
* #param pdfImplementation : the pdfImplementation to get the array of
* custom image objects ImagePDF.
* #param tempPDFFile : the temp PDF file with already HTML content
* converted.
* #param pdf : the final PDF file which will have images stamped.
* #throws DocumentException
* #throws IOException
*/
void addImageToPDF(
PDFInterface pdfImplementation,
File tempPDFFile,
File pdf
) throws DocumentException, IOException {
PdfReader reader = new PdfReader(new FileInputStream(tempPDFFile));
PdfStamper stamper = new PdfStamper(
reader,
new FileOutputStream(pdf)
);
for (ImagePDF img: pdfImplementation.getImages()) {
Image image = img.getImage();
image.scalePercent(img.getScale());
PdfImage stream = new PdfImage(image, "", null);
stream.put(
new PdfName("ITXT_SpecialId"),
new PdfName("123456789")
);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(
img.getWidthPosition(),
img.getHeightPosition()
);
PdfContentByte over = stamper.getOverContent(1);
over.addImage(image);
}
stamper.close();
reader.close();
}
}
3. Create the PDF generator interface
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.itextpdf.text.BadElementException;
/**
* PDFInterface
* Interface to define the behavior a PDF model has to implement.
*/
public interface PDFInterface {
/**
* getUrl
* #param request the HTTPServletRequest to fetch parameters for the PDF
* #return the URL target to make a HTTP POST request to get the generated
* HTML (for example if you are making a HTTP POST on a JSP to generate
* HTML dynamically.
*/
String getUrl(HttpServletRequest request);
/**
* getHTMLFile
* #return return the HTML file from the local storage to be read to get
* the HTML.
*/
File getHTMLFile();
/**
* setParametres
* #param object : an object or a list of objects to be encoded to the
* query String to generate the PDF.
*/
void setParametres(Candidat candidat);
String getEncodedQueryString();
/**
* getImages
* #return a custom ImagePDF object with needed attributes to add an image
* after the PDF has been generated has the HTML cannot be read to get
* image during the generation of the PDF.
*/
List<ImagePDF> getImages();
/**
* addImage
* #param url : the URL to get the image
* #param x : the X position
* #param y : the Y position
* #param name : the name of the image
* #param request : the HTTPServletRequest to generate the relative link
* to fetch the image.
* #param scale : the scale of the image
* #throws BadElementException
* #throws IOException
*/
void addImage(
String url,
float x,
float y,
String name,
HttpServletRequest request,
float scale
) throws BadElementException, IOException;
/**
* getPDFFilename
* #return : the name of the PDF file to be generated
*/
String getPDFFilename();
}
4. The ImagePDF object (in case you need to add image to your PDF)
import java.io.IOException;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;
/**
* ImagePDF
* Class for a custom ImagePDF object to fit needs to stamp an image on a
* generated PDF (URI to get the image, scale, positions x y ...).
*/
public class ImagePDF implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Image image;
private float widthPosition;
private float heightPosition;
private String name;
private Float scale;
/**
* ImagePDF
* #param urlImage : the URL to fetch the image
* #param heightPosition : the y position on the PDF canvas
* #param widthPosition : the x position on the PDF canvas
* #param name : the name of the image
* #param scale : the scale of the image on the PDF canvas
* #throws BadElementException
* #throws IOException
*/
public ImagePDF(
String urlImage,
float widthPosition,
float heightPosition,
String name,
Float scale
) throws BadElementException, IOException {
this.image = Image.getInstance(urlImage);
this.heightPosition = heightPosition;
this.widthPosition = widthPosition;
this.name = name;
this.scale = scale;
}
// Getters and setters ...
5. Implements your interface for your PDF parameters
(used in example above)
/**
* PDFImplementationOne
* The PDFImplementation to generate a specific PDF.
*/
public class PDFImplementationOne implements PDFInterface {
private static final String PARAM_1 = "param1";
private static final String PARAM_2 = "param2";
private Map<String, String> parameters;
private List<ImagePDF> images;
/**
* PDFImplementationOne
* You can pass service to add information retreival from DB or objects to
* pass to parameters in the constructor if needed.
*/
public PDFImplementationOne (CustomObject aParameter) {
this.parameters = new HashMap<>();
this.images = new ArrayList<>();
// in case you need parameters, passed in constructor
setParametres(aParameter);
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#getUrl()
*/
#Override
public String getUrl(HttpServletRequest request) {
/*
* This is an example in case your generate your HTML from JSP with
* parameters, if it is from static file then return null
*/
StringBuilder sb = new StringBuilder("http://");
sb.append(request.getServerName());
sb.append((request.getServerName().startsWith("127.0.0")?":8080":""));
sb.append("/MyApp/urlToJSP");
return sb.toString();
}
/*
* (non-Javadoc)
* #see main.java.interface.PDFInterface#addImage(
* java.lang.String,
* float,
* float,
* java.lang.String,
* javax.servlet.http.HttpServletRequest,
* float scale
* )
*/
#Override
public void addImage(
String fileName,
float x,
float y,
String name,
HttpServletRequest request
) {
/*
* Here I get the image from a ressource server but you can read the
* image from local storage as well
*/
StringBuilder url = new StringBuilder("http://");
url.append(request.getServerName());
url.append(request.getServerName().startsWith("127.0.0")?":8080":"");
url.append("/MyApp/img/");
url.append(fileName);
try {
ImagePDF image = new ImagePDF(url.toString(), x, y, name, scale);
images.add(image);
}
catch (BadElementException | IOException e) {
System.out.println(Cannot set image for PDF "+url.toString());
}
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#getImages()
*/
#Override
public List<ImagePDF> getImages() {
return this.images;
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#setParameters(
* CustomObject customObject
* )
*/
#Override
public void setParametres(CustomObject customObject) {
parametres.put(PARAM_1, customObject.getAttribute().toString());
// may have other parameters ...
}
/* (non-Javadoc)
* #see model.bean.ResultatsEcritsPDF#getEncodedQueryString()
*/
#Override
public String getEncodedQueryString() {
/*
* Create the queryString to do further HTTP POST or GET to fetch the
* generated HTML with parameters
*/
StringBuilder queryStringBuilder = new StringBuilder("?");
parameters.entrySet().stream().forEach(e -> {
queryStringBuilder.append(e.getKey());
queryStringBuilder.append("=");
try {
queryStringBuilder.append(
URLEncoder.encode(
e.getValue() == null
? ""
: e.getValue(),
StandardCharsets.UTF_8.name()
)
);
}
catch (UnsupportedEncodingException e1) {
queryStringBuilder.append("");
}
queryStringBuilder.append("&");
});
// Remove the last &
return queryStringBuilder.toString().substring(
0,
queryStringBuilder.toString().length()-1
);
}
/* (non-Javadoc)
* #see model.bean.PDFInterface#getHTMLFile()
*/
#Override
public File getHTMLFile() {
return new File("/path/to/myHTMLFile.html");
}
/* (non-Javadoc)
* #see model.bean.PDFInterface#getPDFFilename()
*/
#Override
public String getPDFFilename() {
return "myPDF.pdf";
}
}
Tell me if it needs some clarification.
EDIT 2020
Things are much simpler now with the improvement of libraries and calling HTTP server itself to generate the dynamic HTML content is not enough simpler and requires additional network configuration in some case.
Here is the new process :
Make a HTML template with CSS2.1 (with <style> tag or inline style=") and include template expressions (EL-style or whatever)
Fetch HTML template as String
Replace template expressions "${ }" in HTML
Replace images in HTML like <img src="image.png" /> by encoded base64 images
Make the PDF file
Write it to response or whatever
Here is the project structure I am using (for example) :
main
|--java
|--bean
|--PdfConverter.java
|--resources
|--pdf
|--template.html
|--img
|--image.png
Dependencies :
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.20</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.20</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.1.20</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
HTML template (with images) :
<html>
<head>
<style>
body {
font-family:sans-serif;
font-size:14px;
margin: 0 auto;
padding: 0;
}
h1 {
text-align:center;
font-size:21px;
text-transform:capitalize;
}
</style>
</head>
<body>
<h1>some title</h1>
<p>Some paragraph : ${ foo }</p>
<!-- you can style images with CSS! -->
<img src="image.png" style="width:50px;height:50px" />
</body>
</html>
PdfConverter :
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Map;
import java.util.Scanner;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.text.StringSubstitutor;
import org.apache.poi.util.IOUtils;
import org.springframework.http.MediaType;
import org.xhtmlrenderer.pdf.ITextRenderer;
/**
* PdfConverter
* Extends this to implement additional to make the map to replace template
* expressions.
* #author user
* #since 28 juil. 2020
*/
public class PdfConverter {
/**
* Temp directory.
*/
private static final String TMP_DIR =
System.getProperty("java.io.tmpdir") + "/";
/**
* Directory to HTML templates (dedicated to PDF generation).
*/
private static final String PDF_DIR =
"pdf/";
/**
* Directory to the image folders (dedicated to PDF generation).
*/
private static final String PDF_IMG_DIR =
"pdf/img/";
/**
* Prefixes for templates expressions.
*/
private static final String PREFIX_TEMPLATE = "${ ";
/**
* Suffixes for template expressions.
*/
private static final String SUFFIX_TEMPLATE = " }";
/**
* Generated PDF file.
*/
private File generatedPDF;
/**
* PDF file name.
*/
private String pdfName;
/**
* PdfConverter
* #param m map key, value to replace, to replace expressions in HTML
* template.
* #param s ServletContext to get resources from context path.
* #param fileName desired name of the generated PDF.
* #param template name of the HTML template to make the PDF.
* #throws IOExceptio
*/
public PdfConverter(
Map<String, String> m,
ServletContext s,
String fileName,
String template
) throws IOException {
// Set PDF filename
setPdfName(fileName);
// Fetch HTML template
#SuppressWarnings("resource")
String html = new Scanner(
s.getResourceAsStream(PDF_DIR+ template),
StandardCharsets.UTF_8.toString()
).useDelimiter("\\A").next();
/*
* Replace template expressions "${ }" in HTML
*/
StringSubstitutor sub = new StringSubstitutor(
m,
PREFIX_TEMPLATE,
SUFFIX_TEMPLATE
);
String resolvedString = sub.replace(html);
/*
* Replace images like <img src="image.png" /> by
* <img src=\"data:image/png;base64," + base64Image
*/
String[] imgs = StringUtils.substringsBetween(
resolvedString,
"<img src=\"", "\""
);
for (String s1 : imgs) {
String mime = Files.probeContentType(Paths.get(PDF_IMG_DIR + s1));
resolvedString = resolvedString.replace(
s1,
"data:" + mime + ";base64,"
+ Base64.getEncoder().encodeToString(
IOUtils.toByteArray(
s.getResourceAsStream(PDF_IMG_DIR + s1)
)
)
);
}
// Make the PDF file
FileOutputStream fos = new FileOutputStream(TMP_DIR+getPdfName());
ITextRenderer it = new ITextRenderer();
it.setDocumentFromString(resolvedString);
it.layout();
it.createPDF(fos);
fos.close();
// Set the PDF generated file to this PdfConverter instance
setGeneratedPDF(new File(TMP_DIR+getPdfName()));
}
/**
* getGeneratedPDF
*
* #return the generatedPDF
*/
public File getGeneratedPDF() {
return generatedPDF;
}
/**
* setGeneratedPDF
*
* #param generatedPDF the generatedPDF to set
*/
public void setGeneratedPDF(File generatedPDF) {
this.generatedPDF = generatedPDF;
}
/**
* getPdfName
*
* #return the pdfName
*/
public String getPdfName() {
return pdfName;
}
/**
* setPdfName
*
* #param pdfName the pdfName to set
*/
public void setPdfName(String pdfName) {
this.pdfName = pdfName;
}
/**
* writePdfToResponse
* Write the PDF file into the response and delete it from temp directory
* afterwards.
* #param response
* #throws IOException
*/
public void writePdfToResponse(
HttpServletResponse response
) throws IOException {
try (
FileInputStream fis =
new FileInputStream(getGeneratedPDF())
) {
response.setContentType(MediaType.APPLICATION_PDF_VALUE);
response.setHeader(
"Content-Disposition",
"inline; filename=" + getPdfName()
);
response.addHeader(
"Content-Length",
Long.toString(getGeneratedPDF().length())
);
ServletOutputStream servletOutputStream =
response.getOutputStream();
int read = 0;
byte[] bytes = new byte[1024];
while ((read = fis.read(bytes)) != -1) {
servletOutputStream.write(bytes, 0, read);
}
response.flushBuffer();
}
catch (IOException ioe) {
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().print("Cannot render PDF file.");
response.flushBuffer();
}
finally {
// Delete generated PDF after writing it to the response
getGeneratedPDF().delete();
}
}
}
And how to use it in servlet (Spring MVC example) :
/**
* downloadPDF
*
* #param response
* #param foo
* #throws IOException
*/
#PostMapping("/downloadPDF")
public void downloadPDF(
HttpServletRequest request,
HttpServletResponse response,
String foo
) throws IOException {
Map<String, String> m = new HashMap<>();
m.put("foo", "my_foo_value");
PdfConverter pdfConverter = new PdfConverter(
m,
request.getServletContext(),
"my_pdf",
"template"
);
pdfConverter.writePdfToResponse(response);
}
I am developing a web application using Java. From my index page I need to upload a file with some other fields such as some texts and numbers using input tags.
this is my jsp file.
<select name="category">
<option value="">-Select-</option>
<option value="Mobile Phones">Mobile Phones</option>
<option value="Automobile">Automobile</option>
<option value="Computers">Computers</option>
</select><br/><br/>
<label>Title: </label><input type="text" name="Title"/><br/><br/>
<label>Photo: </label><input type="file" name="photo"/><br/><br/>
<label>Description: </label><input type="text" name="description"/><br/><br/>
<label>Price: </label><input type="text" name="price"/><br/><br/>
<input type="submit" value="Post">
I found some articles which use Apache commons, but in all of that, I can get only the image. All the other values get set to null. The article I followed is this.
I need to know how to get other values as well. (In this case category, title, photo etc.)
How can I do that?
Thank you!
EDIT:
This is my servlet.
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.im.dao.PostAdDao;
import com.im.dao.PostAdDaoImpl;
import com.im.entities.Advertiesment;
#WebServlet("/postAd")
#MultipartConfig
public class PostAdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final String UPLOAD_DIRECTORY = "C:/uploadss";
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Advertiesment ad = new Advertiesment();
PostAdDao pad = new PostAdDaoImpl();
PrintWriter out = response.getWriter();
String name = null;
if(ServletFileUpload.isMultipartContent(request)){
try {
List<FileItem> multiparts = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
for(FileItem item : multiparts){
if(item.isFormField()){
String cat = request.getParameter("category");
System.out.println("INFO: Category : "+cat);
if( cat != null ){
ad.setCategory(cat);
}
String title = request.getParameter("adTitle");
if( title != null ){
ad.setTitle(title);
System.out.println("INFO: Title : "+title);
}
String des = request.getParameter("description");
if(des != null){
ad.setDescription(des);
System.out.println("INFO: Description : "+des);
}
try{
Double price = Double.parseDouble(request.getParameter("price"));
if(price != null){
ad.setPrice(price);
System.out.println("INFO: Price : "+price);
}
}catch(Exception e){
System.out.println("ERROR: Occured while setting price in servlet");
}
}else{
name = new File(item.getName()).getName();
item.write( new File(UPLOAD_DIRECTORY + File.separator + name));
}
}
//File uploaded successfully
request.setAttribute("message", "Advertiesment Posted Successfully");
System.out.println("INFO: Advertiesment Posted Successfully");
System.out.println("INFO: File name : "+name);
ad.setPhoto(name);
} catch (Exception ex) {
request.setAttribute("message", "File Upload Failed due to " + ex);
System.out.println("\nERROR: Occured while posting the advertiesment! "+ex );
}
}else{
//request.setAttribute("message","Sorry this Servlet only handles file upload request");
}
//request.getRequestDispatcher("/result.jsp").forward(request, response);
String msg = pad.postAd(ad);
}
}
I found some articles which use Apache commons, but in all of that, I
can get only the image
No . you can get other items also from the request .
DiskFileUpload upload = new DiskFileUpload();
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
//get form fields here
}
else {
//process file upload here
}}
Read the documentation here to understand more on this and also a nice thread here values of input text fields in a html multipart form
Update:
String cat = item.getFieldName("category") instead of request.getParameter("category");
Because you are parsing the request object . so you need to get it from FileItem object . similarly for other fields too.
From the Servlet I am generating JPEG image and writing in the outputstream of that servlet.By jsp i am calling this Servlet URL and displaying the image as similar to user profile with photo.
Here the problem is,When first time login it will generate the image dynamically and display but next time if I login with out closing the browser first it will display the privies picture and then it will display the current picture.
JSP:
<div class="sortable">
<div class="box span5" style="margin-left: 50px;">
<div class="box-header well">
<h2><i class="icon-th"></i>Employee Attendance</h2>
<div class="box-icon">
<i class="icon-chevron-up"></i>
</div>
</div>
<div class="box-content" style="height:230px;" >
<img border="0" src="admissionenquirylist.do?method=image" alt="Pulpit rock" width="370" height="240"/>
</div>
</div>
</div>
Servlet:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.treamis.admission.process;
import com.google.gson.Gson;
import com.treamis.entity.Academicyearmaster;
import com.treamis.entity.AdmissionenquiryStudentdetails;
import com.treamis.entity.EmployeeEntity;
import com.treamis.hr.employee.PaginationClass;
import com.treamis.hr.employee.SetPaginationRecords;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.actions.LookupDispatchAction;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.ServletOutputStream;
/**
*
* #author ranjeeth.g
*/
public class AdmissionEnquiry extends LookupDispatchAction {
/* forward name="success" path="" */
private final static String SUCCESS = "success";
/**
* Provides the mapping from resource key to method name.
*
* #return Resource key / method name map.
*/
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("button.admissionEnqiryList", "admissionEnqiryList");
map.put("button.image", "image");
map.put("button.delete", "delete");
return map;
}
/**
* Action called on Add button click
*/
public void admissionEnqiryList(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
// TODO: implement add method
try {
String stdutendserch = request.getParameter("admissionenquirysearch");
System.out.println("stdutendserch = " + stdutendserch);
Admissionservices as = new Admissionservices();
List<Enquirylistbean> stdserc = as.getStudentEnquirySerch(stdutendserch);
if (stdserc != null) {
response.setContentType("application/json");
String json = new Gson().toJson(stdserc);
System.out.println("json = " + json);
response.getWriter().print(json);
} else {
response.setContentType("application/json");
String json = new Gson().toJson(null);
response.getWriter().print(json);
}
} catch (Exception e) {
e.printStackTrace();
}
// return mapping.findForward(SUCCESS);
// return null;
}
/**
* Action called on Edit button click
*/
public void image(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
try {
System.out.println("Inside the image responce action");
response.setContentType("image/jpeg");
Academicyearmaster academicyearmaster = (Academicyearmaster) request.getSession().getAttribute("academicyear");
// String ss = getServlet().getServletContext().getRealPath("\\");
// String filePath = ss + "img\\paichart.png";
ServletOutputStream out = response.getOutputStream();
// System.out.println("out = " + out);
// String filePath2 = ss + "img\\paichart1.png";
// ExecutorService executor = Executors.newFixedThreadPool(2);
com.treamis.hr.employee.Sendded sendded = new com.treamis.hr.employee.Sendded(out, academicyearmaster);
sendded.image();
// executor.execute(sendded);
} catch (Exception e) {
e.printStackTrace();
}
// TODO: implement edit method
// return mapping.findForward(SUCCESS);
}
/**
* Action called on Delete button click
*/
public ActionForward delete(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws java.lang.Exception {
// TODO:implement delete method
return mapping.findForward(SUCCESS);
}
/* And your JSP would have the following format for submit buttons:
<html:form action="/test">
<html:submit property="method">
<bean:message key="button.add"/>
</html:submit>
<html:submit property="method">
<bean:message key="button.edit"/>
</html:submit>
<html:submit property="method">
<bean:message key="button.delete"/>
</html:submit>
</html:form>
*/
}
Java code to generate image:
try{
ChartUtilities.writeChartAsJPEG(out, chart, 600, 400, info);
// System.out.println("file2 = " + file1);
} catch (Exception e) {
e.printStackTrace();
return "success";
} finally {
out.close();
}
The answer lies in the Life cycle of Servlet. Even though multiple request comes to a servlet only one instance of the Servlet class will be created.
Check if you have any resources that is global and fix it.
Or post full servlet class for better response.
Hope it helps!
I think if you use differents files names to each file save in disk you will not have this problem again.
My project has been created by GAE Plugin for Eclipse (without Maven) and i'm goint to post my code composed by:
home.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Upload Test</title>
</head>
<body>
<form action="/upload" method="post" name="putFile" id="putFile"
enctype="multipart/form-data">
<input type="file" name="myFile" id="fileName">
<input type="submit" value="Upload">
</form>
</body>
</html>
UploadServlet.java:
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();
}
}
}
I tried also to set the maximumSize of the Upload using upload.setMaxSize(-1); or changing the BUFFER_SIZE from 2*1024*1024 into 200*1024*1024, but the issue stil occur. To be more specific, when the uploading reach the 100% I receive this message on the webpage:
Error: Request Entity Too Large Your client issued a request that was too large.
How can i fix that using JAVA and Google Cloud Storage Client Library for Java? (I'm not going to change drastically the Project with other Programming Languages)
Could you please help me to find a solution? Thank you so much!
App Engine request limit is 32Mb. That's why your uploads are failing when you send a file > 32Mb. Checkout Quotas and Limits section.
You have two options for uploading files > 32Mb:
Blobstore API.
You can specify a GCS bucket instead of using Blobstore storage space.
To do that use createUploadUrl(java.lang.String successPath, UploadOptions uploadOptions) method of BlobstoreService.
Here's a sample app: https://github.com/crhym3/java-blobstore-gcs-sample
Signed URLs feature of GCS
Or you could just use Google Drive and store only doc IDs in the datastore :)
I will suggest you to take a look at this great and sample example: http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html
A good idea will be to monitor the data stream to the server.
Hope it helps
I am new to JAVA technology,especially Servlets.I need to make a Web application project which have an upload and a download files to/from a server(tomcat).I have already an upload servlet,which works fine.
i have also a download servlet,found on the internet.But the problem is that this servlet allows downloading only a specific file,and the path to this specific file is given in the servlet. I need to let the client see the entire content of my upload folder and select which file he wants to download from this folder.
The code of the download servlet is this:
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();
}
}
The JSP page is this:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Download Servlet Test</title>
</head>
<body>
Click on the link to download: Download Link
</body>
</html>
I searched a lot of servlets but all of them were like this...they allowed downloading only a specific file.
Can anyone help me?
Thank you very much!
Since you're handling the data on the doGet method, you can pass a parameter to the servlet where you indicate the name of the file you want to download. For this, you should assume that the file name exists in your base path. The code could go like this:
HTML
<body>
Click on the link to download:
Download Link
</body>
Java Servlet Code:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//retrieving the parameter by its name
String fileName = request.getParameter("fileName"); //this will return `data.xls`
//using the File(parent, child) constructor for File class
File file = new File(filePath, fileName);
//verify if the file exists
if (file.exists()) {
//move the code to download your file inside here...
} else {
//handle a response to do nothing
}
}
Note that since the code now uses File(String parent, String child) constructor, your filePath should not contain the separator anymore (this will be handled by Java):
public void init() {
// the file data.xls is under web application folder
filePath = getServletContext().getRealPath("");
}
you can do like that
public void doGet(HttpServletRequest req, HttpServletResponse res){
res.setContentType("text/html);
PrintWriter out=response.getWriter();
String fileName="home.txt";
String filePath="d:\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment;fileName=\""+fileName+"\"");
int i;
FileInputStream file=new FileInputStream(filePath +fileName);
while((i=file.read()) !=-1){
out.write(i);
}
file.close();
out.close();
}
// get MIME type of the file
String mimeType = context.getMimeType(fullPath);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// set content attributes for the response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
This more detail and the question how to improve:https://stackoverflow.com/questions/41914092/how-change-servlet-which-download-single-file-but-can-folderfew-files-in-fold