multipart/form-data not working with servlets - java

I am not really sure why the html form with the tag enctype="multipart/form-data" does not pass the objects it should pass. this is the case with mozilla and firefox.
for IEs case, for example, I use html control to choose a file, it does get what it is supposed to get.
Now I just want to know if there are any alternatives I can use to pass in files through http request object because the enctype="multipart/form-data" seems to be having some compatibility issues but I am not really sure
any suggestions would be appreciated! :D

First of all, you have to provide a little bit of code to show what you have done, and to know what went wrong. Anyway, I am assuming that you have to upload a file to the server using HTML file upload control.
File upload or to say multipart/form-data encoding type support is not implemented in HttpServlet implementation. So, the request.getParameter() don't work with multipart/form-data. You have to use additional libraries which provide support for this. Apache Commons File Upload is a good example. Their using fileupload guide will help you to get started with the library. Here is a simple example (compiled from using file upload guide).
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
// Process form field.
String name = item.getFieldName();
String value = item.getString();
} else {
// Process uploaded file.
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
if (writeToFile) {
File uploadedFile = new File("path/filename.txt");
item.write(uploadedFile);
}
}
}
} else {
// Normal request. request.getParameter will suffice.
}

got it. if someone else might have a problem like this, this was my problem. i checked the content type of the file for me to ensure that the objects passed is of a certain type. in IE, it returns application/x-zip-compressed THAT IS ONLY FOR IE but mozilla and chrome seems to be returning a different content type for the zip file which is application/octet-stream.
so i just added the application/octet-stream to the valid filetypes and it seems to be working now

Related

Check real file size while streaming files with FileItemStream

I'm writing an API using Spring + apache commons file upload.
https://commons.apache.org/proper/commons-fileupload/
There is a problem that I faced. I need to validate a file size. If it's bigger then the one that I configure, user should get an error.
For now, I implemented the upload without this check and it looks like this:
public ResponseEntity insertFile(#PathVariable Long profileId, HttpServletRequest request) throws Exception {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator uploadItemIterator = upload.getItemIterator(request);
if (!uploadItemIterator.hasNext()) {
throw new FileUploadException("FileItemIterator was empty");
}
while (uploadItemIterator.hasNext()) {
FileItemStream fileItemStream = uploadItemIterator.next();
if (fileItemStream.isFormField()) {
continue;
}
//do stuff
}
return new ResponseEntity(HttpStatus.OK);
}
It does exactly what I need. It doesn't require me to get file loaded completely to the memory. I use InputStream that I got to perform further transfer to another service. Eventually, I don't have file loaded to the memory completely at any point of the time.
However, that prevents me from getting the total number of bites that were loaded.
Is there a way to handle such validation without downloading file completely or saving it somewhere?
I tried FileItem, but it does require complete loading of the file.
ServletFileUpload has a method setSizeMax that control the max file size accepted for each request. To mitigate memory consumption issues you can use a DiskFileFactory to set disk file storing for larger files. You must always get the files cause trusting in headers only is not reliable but I think this will do the job :)

JSP Writing to server directory

So I am using resumable.js to upload files to a server.
The directory that I want to save to is something like
/dir/files/upload/
Obviously just made up, but this directory has user permissions to write to it.
I am using JSP to listen to the POST request that resumable.js makes, and writing the
.part
files to that directory.
Sample listener:
<% if(request.getMethod().equals("POST") && request.getParameter("resumableFilename") != null){
long chunkSize = StringUtils.isEmpty(request.getParameter("resumableChunkSize"))? 0:Long.parseLong(request.getParameter("resumableChunkSize"));
String fileName = request.getParameter("resumableFilename");
long totalSize = StringUtils.isEmpty(request.getParameter("resumableTotalSize"))? 0:Long.parseLong(request.getParameter("resumableTotalSize"));
String temp_dir = "/dir/files/upload/"+request.getParameter("resumableIdentifier");//Add in user_id
String dest_dir = temp_dir+fileName+".part"+request.getParameter("resumableChunkNumber");
File fDir = new File(temp_dir);
fDir.mkdirs();
if(ServletFileUpload.isMultipartContent(request)){
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(temp_dir)); ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request);
ArrayListIterator iter = (ArrayListIterator)items.iterator();
FileItem item = (FileItem)iter.next();
File fileWithNewDir = new File(dest_dir);
item.write(fileWithNewDir); // write file to dest_dir (fileName.part*CHUNK_NUM*)
}
}
%>
The script is hosted on
www.site.com/pubs/res.jsp
According to the JS itself for resumable, the process of uploading it gets completed, however, a new directory is not made at all. I know it's not the write permissions, so it must be something else.
Here is my call in javascript for a new resumable object
var resume = new Resumable({
target:"res.jsp",
resumableChunkSize: 1*1024*1024,
simultaneousUploads: 3,
testChunks: false,
throttleProgressCallbacks: 1
});
It seems to be hitting the jsp file, but nothing is happening.
I followed Apache's fileupload page in order to implement that listener, but maybe I went wrong at some point.
Apache's FileUpload
Resumable.js
Location of the directory matters. It has to be within the context of the WAR. You cannot write to any location outside the context of the container. If you look at the log you may be abe to see the error message which can explain this.

how to save large files inside the data base.?

I am using JSP form to upload and Servlet to store a large-sized file in a MySQL database. and because i am new to Java in general, i need a really urgent help.
I tried to store the file in a String value but i got error that string index is out of boundary.
I have the database table Files which has (varchar File_Name, Blob File_data, Varchar File_Date) .
And i need to store the uploaded file inside the
I had this code in servlet:
** BTW : i have no idea why "DiskFileUpload, parseRequest " have strikethrough line ?
try {
InputStream uploadedFile = null;
<strike>DiskFileUpload</strike> fu = new </strike>DiskFileUpload</strike>();
// If file size exceeds, a FileUploadException will be thrown
fu.setSizeMax(10000000);
List fileItems = fu.<strike>parseRequest</strike>(request);
Iterator itr = fileItems.iterator();
while (itr.hasNext()) {
FileItem fi = (FileItem) itr.next();
//Check if not form field so as to only handle the file inputs
//else condition handles the submit button input
if (!fi.isFormField()) { // If the form fiel is a file
uploadedFile = fi.getInputStream();
}
What type of data should I convert uploadFile cvariable to be able to store it in a Blob attribute ?
Strike through means API is deprecated and those classes/methods may not work as expected.
Storing file to database, you need to store the content as bytes in blob filed. See this discussion. Even though it is related to some error, OP posted code on how to do this.

How to upload a directory via Grails or Java?

What is the best way to upload a directory in grails ?
I try this code :
def upload = {
if(request.method == 'POST') {
Iterator itr = request.getFileNames();
while(itr.hasNext()) {
MultipartFile file = request.getFile(itr.next());
File destination = new File(file.getOriginalFilename())
if (!file.isEmpty()) {
file.transferTo(destination)
// success
}
else
{
// failure
}
}
response.sendError(200,'Done');
}
}
Unfortunately, I can only upload file by file.
I would like to define my directory, and upload all files directly.
Any ideas ?
There is one major misconception here. The code which you posted will only work if both the server and the client runs at physically the same machine (which won't occur in real world) and if you're using the MSIE browser which has the misbehaviour to send the full path along the filename.
You should in fact get the contents of the uploaded file as an InputStream and write it to any OutputStream the usual Java IO way. The filename can be used to create a file with the same name at the server side, but you'll ensure that you strip the incorrectly by MSIE sent path from the filename.
As to your actual functional requirement, HTML doesn't provide facilities to upload complete directories or multiple files by a single <input type="file"> element. You'll need to create a client application which is capable of this and serve this from your webpage, like a Java Applet using Swing JFileChooser. There exist 3rd party solutions for this, like JumpLoader.

JSP: I am doing an application in which i have to download ppt file

I am working on an application wherein I have to download a PPT file using a JSP page. I am using the following code, but it's not working.
<% try {
String filename = "file/abc.ppt";
// set the http content type to "APPLICATION/OCTET-STREAM
response.setContentType("APPLICATION/OCTET-STREAM");
// initialize the http content-disposition header to
// indicate a file attachment with the default filename
// "myFile.txt"
String disHeader = "Attachment Filename=\"abc.ppt\"";
response.setHeader("Content-Disposition", disHeader);
// transfer the file byte-by-byte to the response object
File fileToDownload = new File(filename);
FileInputStream fileInputStream = new
FileInputStream(fileToDownload);
int i;
while ((i=fileInputStream.read())!=-1)
{
out.write(i);
}
fileInputStream.close();
out.close();
}catch(Exception e) // file IO errors
{
e.printStackTrace();
}
%>
Can anybody solve this problem?
Not only the Content-Disposition header is incorrect, but you're incorrectly using JSP instead of a Servlet for this particular task.
JSP is a view technology. Everything outside the scriptlets <% %> will be printed to the response, including whitespace characters such as newlines. It would surely corrupt binary files.
You could trim the whitespace in the JSP file, but scriptlets are discouraged since a decade and nowadays considered bad practice. Raw Java code belongs in Java classes, not in JSP files. The real solution is to use a HttpServlet for this.
Create a class which extends HttpServlet, implement the doGet() method, move the Java code from the JSP file into this method, map this servlet on a certain url-pattern and your problem should disappear. You can find here a basic example of such a servlet.
Off the top there should be a semicolon in the Content-Disposition header ("attachment*;* filename ...)
You should also probably do a response.reset() before starting to set headers and stream. Internet Explorer has really strange rules about streaming files from secure sockets and won't work right if you don't clear the caching headers.

Categories