I was going over a nodejs tutorial which mentioned that Node.JS does not keep the file in memory when writes files to a disk and it flushes chunks of file to disk as and when it receives it. Is Java capable of handling file in a similar fashion or does it keep the entire file in memory before flushing to disk? In the past , I have faced out of memory exception when I tried to upload files using servlets.
The answer is Yes, In java you can use streaming APIs that can help you do it.
try the following guide to understand it better :
http://commons.apache.org/proper/commons-fileupload/streaming.html
Example :
Fileupload using Servlet:
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
ow we are ready to parse the request into its constituent items. Here's how we do it:
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
} else {
System.out.println("File field " + name + " with file name " + item.getName() + " detected.");
// Process the input stream
...
}
}
And at last you can write the input stream in a file using the follwing approach :
FileOutputStream fout= new FileOutputStream ( yourPathtowriteto );
BufferedOutputStream bout= new BufferedOutputStream (fout);
BufferedInputStream bin= new BufferedInputStream(stream);
int byte;
while ((byte=bin.read()) != -1)
{
bout.write(byte_);
}
bout.close();
bin.close();
Related
I am fetching S3 objects and then sending the object in email as an attachment. I am saving the contents in a temporary file. For images the code is working fine but in case of documents (pdf, docx, csv) files the attachments are sent without extension so they are not accessible.
try {
fullObject = s3Client.getObject(new GetObjectRequest(bucketName, key));
System.out.println("fullObject: " + fullObject);
ObjectMetadata metadata = fullObject.getObjectMetadata();
System.out.println(" meta data type: " + metadata.getContentType());
InputStream inputStream = fullObject.getObjectContent();
String extension = fullObject.getKey();
int index = extension.lastIndexOf('.');
if(index > 0) {
extension = extension.substring(index + 1);
System.out.println("File extension is " + extension);
}
File file = File.createTempFile(key, "."+ extension );
System.out.println("file: "+ file);
try (OutputStream outputStream = new FileOutputStream(file)) {
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
System.out.println("error in copying data from one file to another");
}
dataSource = new FileDataSource(file);
System.out.println("added datasource in the list");
attachmentsList.add(dataSource);
}
Upon going through this code, I got to know that the issue was not in this code but when I was setting the name of the File. I was setting filename without any extension, for example I set Filename as "temporary" this caused the documents to be saved with tmp extension. All I had to do was add the extension of the object with its name ("temporary.docx"), this solved the issue and attachments were sent properly and were accessible.
I am trying to upload a file from jsp page. I am successful to get all the fields from the jsp file but can able to read the file which i get uploaded in the jsp. I am uploading a zip file from the jsp page. here is my code.
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(req);
while (iter.hasNext()) {
FileItemStream item = iter.next();
if (!item.isFormField()) {
String name = item.getFieldName();
System.out.println("File field " + name + " with file name " + item.getName() + " detected.");
InputStream stream = item.openStream();
BuildVO buildVO = buildDAO.findByFileName(item.getName());
ZipEntry entry;
ZipInputStream zis = new ZipInputStream(stream);
while ((entry = zis.getNextEntry()) != null ) {
System.out.println(buildVO.getOriginalFileName()+">>>>>>>>>>>>>>>>>>>>fileFound??????"+entry.getName());
}
}
}
with this code i get the input stream of a uploaded file. But from that i cannot able to read the zip file and it contents.Any one can help me?
I have a servlet application that need to receive some files from some clients (in general not html\javascript based!) and I have to limit the filesize for each file. Thisi is a classical problem.
The streaming API of the apache fileUpload allow to stream a multi-part request to the server avoiding the need of saving the request content in temporary files before they are processed. Is this Correct?
Anyway with this approach I obviously can't know the actual filesize.
What I though was:
The client knows the file size. So it will send a form-field containing the file size.
The content-length http header contains the request size, so I can take it as an upperbound of the filesize
I can count the bytes I'm saving
Now assuming that I want to make all the necessary validations server-side. This because I'm paranoic and I don't trust the clients, then:
a. options (1) and (2) are useful in case "good" clients make bad requests. So a first validation can be based on that.
b. option (3) is the only completely server-side option I found. So it is needed.
So I though that I could count the bytes I read and if the file exceedes the size-limit I print errors, delete the file I was writing and then make the "return" in servlet doPost.
Am I doing right or there are some other better way to go?
Try like this into your Servlet, also get all information about file from item
//TODO Create and check tmpDir & destinationDir then do as below
PrintWriter out = response.getWriter();
response.setContentType("text/xml;charset=UTF-8");
File file = null;
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
fileItemFactory.setSizeThreshold(10 * 1024 * 1024);
fileItemFactory.setRepository(tmpDir); /* Set the temporary directory for uploaded files of size above threshold. */
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
try {
List items = uploadHandler.parseRequest(request);
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.getSize() <######||item.getSize() > 0){ // Where you can control file size
if (item.isFormField()) {
System.out.println("Field = " + item.getFieldName() + ", Value = " + item.getString());
} else {
System.out.println("Field Name = " + item.getFieldName() + ", File Name = " + item.getName() + ", Content type = " + item.getContentType() + ", File Size = " + item.getSize());
file = new File(destinationDir, item.getName()); ///Destination for permanent save*/
item.write(file);
}
out.println("Upload success");
}else{
out.println("File Size is not be zero OR more than ####");
}
}
} catch (FileUploadException ex) {
out.println("Upload Failed" + ex.getMessage());
log("Error while parsing the request", ex);
} catch (Exception ex) {
out.println("Upload Failed" + ex.getMessage());
log("Error while uploading file", ex);
}
out.close();
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to upload files to server using JSP/Servlet?
I'm implementing a fileupload servlet that is used alongside resumable.js
Everytime I try to read a file, I either get a NoSuchElement exception or a NumberFormatException with a string inside the file I'm reading. I'm sure I made a hiccup somewhere, but can't seem to tell
Here's a snippet of what I use to read request and write to file
if(ServletFileUpload.isMultipartContent(request)){
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(temp_dir));
ServletFileUpload upload = new ServletFileUpload(factory);
Iterator<FileItem> iter = upload.parseRequest(request).iterator();
FileItem item = iter.next();
OutputStream out;
try {
out = new FileOutputStream(new File(dest_dir));
IOUtils.copy(item.getInputStream(), out);
logger.debug("Wrote file " + resumableIdentifier + " with chunk number "
+ resumableChunkNumber + " to " + temp_dir);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
}
Did I do something wrong that is making the code actually read and interpret the contents of the file?
You have to iterate over the FileItems.
Right after this line:
Iterator<FileItem> iter = upload.parseRequest(request).iterator();
You should have something like this:
File dir = new File(dest_dir);
if (!dir.isDirectory()) dir.mkdirs();
while(iter.hasNext()) {
FileItem item = iter.next();
Also do not forget to close the output stream for every file item.
out = new FileOutputStream(new File(dir, item.getName()));
IOUtils.copy(item.getInputStream(), out);
out.close();
I have written a Java web application that allows a user to download files from a server. These files are quite large and so are zipped together before download.
It works like this:
1. The user gets a list of files that match his/her criteria
2. If the user likes a file and wants to download he/she selects it by checking a checkbox
3. The user then clicks "download"
4. The files are then zipped and stored on a servera
5. The user this then presented with a page which contains a link to the downloadable zip filea
6. However on downloading the zip file the file that is downloaded is 0 bytes in sizea
I have checked the remote server and the zip file is being created properly, all that is left is to serve the file the user somehow, can you see where I might be going wrong, or suggest a better way to serve the zip file.
The code that creates the link is:
<%
String zipFileURL = (String) request.getAttribute("zipFileURL"); %>
<p>Zip File Link</p>
The code that creates the zipFileURL variable is:
public static String zipFiles(ArrayList<String> fileList, String contextRootPath) {
//time-stamping
Date date = new Date();
Timestamp timeStamp = new Timestamp(date.getTime());
Iterator fileListIterator = fileList.iterator();
String zipFileURL = "";
try {
String ZIP_LOC = contextRootPath + "WEB-INF" + SEP + "TempZipFiles" + SEP;
BufferedInputStream origin = null;
zipFileURL = ZIP_LOC
+ "FITS." + timeStamp.toString().replaceAll(":", ".").replaceAll(" ", ".") + ".zip";
FileOutputStream dest = new FileOutputStream(ZIP_LOC
+ "FITS." + timeStamp.toString().replaceAll(":", ".").replaceAll(" ", ".") + ".zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
// out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
while(fileListIterator.hasNext()) {
String fileName = (String) fileListIterator.next();
System.out.println("Adding: " + fileName);
FileInputStream fi = new FileInputStream(fileName);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(fileName);
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return zipFileURL;
}
A URL cannot access any files (directly) under WEB-INF. I'd suggest using a servlet to return the file from whatever location it was saved to
Would also suggest saving the file outside the context of your webapp