Upload file using Spark framework and FreeMarker - java

I'm trying to make a method to upload files using the spark framework and freemarker but I seem to be hitting a brick wall at the .getPart method. My current freemarker code looks as follows:
<form method='post' enctype='multipart/form-data'>
<div>
<input type='file' name='uploadedFile'>
<button>Upload csv</button>
</div>
</form>
and my spark java post method code looks as follows:
post(new Route("/pdf", "multipart/form-data") {
#Override
public Object handle(Request request, Response response) {
String name = null;
File upLoadM = new File("messages/");
Path tempFile = null;
Part file = null;
try {
tempFile = Files.createTempFile(upLoadM.toPath(), "", "");
System.out.println(tempFile);
}
catch (IOException e1) {
e1.printStackTrace();
}
request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
try {
file = request.raw().getPart("uploadedFile");
System.out.println(file);
}
catch (IOException | ServletException e1) {
e1.printStackTrace();
}
try (InputStream input = file.getInputStream()) {
Files.copy(input, tempFile, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
e.printStackTrace();
}
response.status(201);
response.redirect("/pdf");
return "";
}
});
When i hit the upload button I get a 500 Internal Error. Not sure what the reason it's crashing at the .getPart method is. Any help would be appreciated.

Turns out it is working if i tweek the line of code:
request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
to
request.attribute("org.eclipse.multipartConfig", new MultipartConfigElement("/temp"));

Related

Unable to visualize pdf file after submitting via FilePond component in React to a servlet(backend)

I have a front React application with an upload document form via FilePond library and as backend I use Java to save the pdf document to my local files.
I am a little bit stucked beacause I have the pdf file and I can see the content(in Notepad/Code) but when I open it with Adobe/Microsoft Edge all pages are blank I don't know why.
In FilePond documentation it's not specified the defaut encoding and I don't know there is a way to see the encoding in the request(req).Also if it's not possible in this way how th send the file with getFileEncodeBase64String. Thank you very much for any ideas.
Code in React :
const APIClient = axios.create({
// baseURL: 'https://postman-echo.com',
baseURL: Config.faqServerUrl,
timeout: Config.timeout,
headers: {
'Accept': 'application/json;charset=UTF-8',
'Content-Type': 'application/json;charset=UTF-8'
}
});
Call backend :
function processFile(fieldName, file, metadata, load, error, progress, abort, setFileName) {
const formData = new FormData();
let feedbackWS = null;
formData.append('file', file, file.name);
try{
feedbackWS = APIClient.post('/upload-document',formData, {
onUploadProgress: (e) => {
// updating progress indicator
progress(e.lengthComputable, e.loaded, e.total);
}
}).then((response) => {
load(response.data);
setFileName(response.data);
})
.catch((error) => {
console.error(error);
});
} catch (error) {
console.log(error);
}
}
FilePond component :
<FilePond
server={{
process:(fieldName, file, metadata, load, error, progress, abort) => {
processFile(fieldName, file, metadata, load, error, progress, abort);
}
}}
oninit={() => handleInit()}
// callback onupdatefiles- a file has been added or removed, receives a list of file items
onupdatefiles={(fileItems) => {
// Set current file objects to this.state
setFile(fileItems.map(fileItem => fileItem.file));
}}
instantUpload={true}
onprocessfile={(error, file)=>{
console.log('PROCESSED', file, 'SERVER_ID', file.serverId);
// console.log('ERROR PROCESSED', error);
}}
onaddfile={(error, file)=>{
console.log('PROCESSED', file, 'SERVER_ID', file.serverId);
// console.log('ERROR PROCESSED', error);
}}
/>
Java code :
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("encoding" + req.getCharacterEncoding()); // it is null
nom_upload_faq = "test.pdf";
String repertoireFaqTemp = "/temp/";
String pathComplet = repertoireFaqTemp + nom_upload_faq;
File fichierTemp = null;
try {
fichierTemp = new File(pathComplet);
if (fichierTemp.exists() && fichierTemp.isFile()) {
fichierTemp.delete();
}
if (fichierTemp.createNewFile()) {
fichierTemp.setReadable(true, false);
fichierTemp.setWritable(true, false);
fichierTemp.setExecutable(true, false);
fichierTemp.deleteOnExit();
} else {
System.out.println("Impossible d'arriver ici on l'a déjà supprimer avant");
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
//byte[] fileAsBytes = getArrayFromInputStream(req.getInputStream());
byte[] fileAsBytes = null;
try {
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(req);
for (FileItem item: items) {
if(!item.isFormField()) { // it'a file
fileAsBytes = getArrayFromInputStream(item.getInputStream());
}
}
} catch (FileUploadException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(fichierTemp))) {
output.write(fileAsBytes);
output.flush();
output.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] getArrayFromInputStream(InputStream inputStream) throws IOException {
byte[] bytes = null;
byte[] buffer = new byte[1024];
try (BufferedInputStream is = new BufferedInputStream(inputStream)) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int length;
while ((length = is.read(buffer)) > -1) {
bos.write(buffer, 0, length);
}
bos.flush();
bytes = bos.toByteArray();
} catch (Exception e) {
System.out.println("toto");
}
return bytes;
}
Edit: Thank you Rik indeed the call formData.append('file', file, file.name); is the right one but still the same problem with the encoding(adding ? symbol) this is why I thought that it will be maybe the only possiblity to send the pdf file as base64 I've installed the plugin but as it'a asyncronous I can't call the methods getFileEncodeBase64String and in the servlet the request stream it's not the right one as you can see in the picture.
here you can see the sequence before the mouse selection I have an 8 with ?
You don't have to encode the file
formData.append('file', file.getFileEncodeBase64String(), file.name);
You can do:
formData.append('file', file, file.name);
And your browser will post a file object which you can handle like any other file posted with a form. See: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects

Generate doc use docx4j, it gose different on windows and linux server

when I use docx4j to generate doc from HTML and output through java servlet, it works well on Windows system, I can download and open the doc file normally.
When I put the project on Linux server, I can also download the doc file, but when openging file, it alert that the file is broken. I must click the confirm and restore the file.then open it normally.
my core code is like this.
how can i get the same result as windows?
code in jsp:
String vhtml = DownHtml2DocUtil.replaceSvgData2Base64(request);
response.reset();
response.setContentType("application/octet-stream");//设置为字节流
OutputStream output = null;
try {
output = response.getOutputStream();
response.addHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis() + ".doc");
DownHtml2DocUtil.genDocFromHtml(vhtml, output);
} catch (Exception e) {
} finally {
try {
if (output != null) {
output.close();
}
} catch (Exception e) {
}
}
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
code in java like this:
public static void genDocFromHtml(String html, OutputStream out)
throws EMPException {
try {
WordprocessingMLPackage wordMLPackage;
wordMLPackage = WordprocessingMLPackage.createPackage();
XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(
wordMLPackage);
wordMLPackage.getMainDocumentPart().getContent()
.addAll(XHTMLImporter.convert(html, "utf-8"));
// wordMLPackage.save(out); -- i tried both method
new Save(wordMLPackage).save(out);
} catch (InvalidFormatException e) {
throw new EMPException(e);
} catch (Docx4JException e) {
throw new EMPException(e);
} catch (Exception e) {
e.printStackTrace();
}
}
any suggestion will be appreciate , thanks anyway;

Spring MVC Safe way to Upload, generate and download a file

I´m working on a WebApp with Spring MVC and Maven. I have the following process: First of all the User has to upload a file. Afterwards the uploaded file will be edited. Last but not least I want to create a download which contains the edited file.
The first step "Upload File" works well. I have a controller which contains the following POST method:
#RequestMapping(value = "/CircleUp", method = RequestMethod.POST)
public String circleUpPost(HttpServletRequest request, Model model, //
#ModelAttribute("circleUpForm") CircleUpForm circleUpForm) {
return this.doUpload(request, model, circleUpForm);
}
private String doUpload(HttpServletRequest request, Model model, //
CircleUpForm circleUpForm) {
File file = circleUpForm.getFile();
if (file != null) {
try {
//Some edit stuff
serialize(file, SerializationModeEnum.Standard);
} catch (Exception e) {
e.printStackTrace();
}
}
model.addAttribute("uploadedFiles", file);
return "uploadResult";
}
protected static String serialize(File file, SerializationModeEnum serializationMode) {
java.io.File test = null;
try {
test = java.io.File.createTempFile("Test", ".pdf");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
file.save(test, serializationMode);
} catch (Exception e) {
e.printStackTrace();
}
// test.deleteOnExit();
return test.getPath();
}
In the "serialize" Method my PDFClown File will be saved to a temp folder.
Afterwards the "uploadResult" page will be appear which contains the folloing code:
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<meta charset="UTF-8">
<title>Download</title>
</head>
<body>
<h3>Download Files:</h3>
CircleUp
</body>
</html>
When the User clicks on the link another Controller will be called which handles the download. I dont know how to design the controller so that it can works with the edited file which I saved in my temp folder. I think it should look like that :
#RequestMapping(value = "/Download")
public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {
final String temperotyFilePath = ???
String fileName = "Test.pdf";
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos = convertPDFToByteArrayOutputStream(temperotyFilePath + "\\" + fileName);
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
} catch (Exception e1) {
e1.printStackTrace();
}
}
private ByteArrayOutputStream convertPDFToByteArrayOutputStream(String fileName) {
InputStream inputStream = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
inputStream = new FileInputStream(fileName);
byte [] buffer = new byte [1024];
baos = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return baos;
}
I have two questions now:
How can the DownloadController attain the temp path to the file?
Is this process of Uploading,Generating and Downloading a File safe? Or is there a better way to handle this process?
I´m new to Spring MVC and WebApp Development and I´m thankful for every suggestion :)
You can use the same approach you use in the upload
test = java.io.File.createTempFile("Test", ".pdf");
All you need is to point to the same file and then read it.
If you need a custom dir for the files saving you can either define a property - my.file.path=some path here or
use system temp dir
public class Main {
public static void main(String[] args) {
String property = "java.io.tmpdir";
String tempDir = System.getProperty(property);
System.out.println("OS current temporary directory is " + tempDir);
}
}
Got the code from the link
Actually the approach is not safe. What to do if 2 different users upload files with the same name& What if one is uploaded and another user tries to download it? What is amount of files is millions? etc. etc.
It's better to use independent file storage but for test project it's fine

Spark (JAVA): how to read and save data file from the http body(Audio file)?

I kinda know how to see the data from the request, however I'm not sure how to handle it.
post("/", (req, res) -> {
System.out.println(req.body());
return "something";
});
which shows me:
--1Wbh7zeSxsgY0YXI6wHO8nmxeVk4iV
Content-Disposition: form-data; name="file"; filename="1455896241350.m4a"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Data data ... etc
How to get the file attached with the body and save it in the server so later on I could use it?
*------------------------ * ------------------------ * ------------------------*
I've tired this code:
try {
FileOutputStream fis = new FileOutputStream(new File("audio.m4a"));
System.out.println("file created");
try {
int offset = 186;
fis.write(req.bodyAsBytes(), offset, req.bodyAsBytes().length - offset);
fis.close();
System.out.println("file wrote");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("done");
it worked fine for me, but it is static or hard-coded, I need it dynamic.
(Note/ I skiped the first 186 bytes which are the header of the http, so I need to get there dynamically not the hard-coded way)
get("/upload", (request, response) -> {
return new ModelAndView(null, "upload.ftl");
}, new FreeMarkerEngine());
post("/upload", "multipart/form-data", ((request, response) -> {
try {
request.raw().setAttribute("org.eclipse.jetty.multipartConfig",
new MultipartConfigElement("/tmp", 100000000, 100000000, 1024));
String filename = request.raw().getPart("file").getSubmittedFileName();
Part uploadedFile = request.raw().getPart("file");
try (final InputStream in = uploadedFile.getInputStream()) {
Files.copy(in, Paths.get("/tmp/"+filename));
}
uploadedFile.delete();
} catch (Exception e) {
throw new RuntimeException(e);
}
return new ModelAndView(null, "upload.ftl");
}), new FreeMarkerEngine());
upload.ftl
<form action="/upload" enctype="multipart/form-data" method="post">
<label for="file">File to send</label>
<input type="file" name="file"><br>
<input type="submit" value="Upload">
</form>
please excuse the hacky exception handling
this requires Spark 2.3
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.3</version>
</dependency>

Spring + GWTP: Excel file download from OutputStream not working

I have a GWTP application to export some data to an .xlsx file using Apache POI. Here is my presenter code.
protected void exportTable(String selectedPublisher, String selectedTarget, Drilldown drilldown) {
this.excelServiceAsync.generateDataEnrichmentExport(selectedPublisher, new AsyncCallback<Void>() {
#Override
public void onSuccess(Void result) {
Window.open(GWT.getModuleBaseURL() + "rpc/excelDownload", "_blank", "");
}
#Override
public void onFailure(Throwable caught) {
Window.alert("Error!");
}
});
}
Here is my excel generation code which is asynchronously called by the presenter.
workbook = new XSSFWorkbook();
sheetOne = workbook.createSheet("Export One");
// TODO Typical POI coding stuff
FileOutputStream out = null;
try {
out = new FileOutputStream(new File("file.xlsx"));
workbook.write(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
And here is my controller which I use to download the excel file.
#ResponseBody
#RequestMapping(value = "/excelDownload")
public String downloadExcel(HttpServletRequest request, HttpServletResponse response){
File file = new File("file.xlsx");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename="
+ "file.xlsx");
response.setHeader("Content-Length", String.valueOf(file.length()));
FileInputStream is = null;
try {
is = new FileInputStream(file);
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
response.getOutputStream().close();
} catch (FileNotFoundException e) {
logger.error(e.getMessage(), e.getCause());
} catch (IOException e) {
logger.error(e.getMessage(), e.getCause());
} finally {
try {
is.close();
} catch (Exception ex) {
return "redirect:/error/internal";
}
}
return "";
}
I'm generating the excel file and putting on the output stream. Then in the controller I get the data from the output stream to download as an .xlsx file. This isn't working. The working file is generated and saved on the server. But the file that is downloaded by the browser is a corrupted file. I'm not really sure why. Please help!
You forgot to close your FileOutputStream out. Maybe try using the try (resource) {...} syntax of Java7?
Try set response.setContentLength((int) file.length());

Categories