Original file name after upload? - java

How do you get the original filename uploaded on GAE?
Going based on the following example:
https://developers.google.com/appengine/docs/java/blobstore/overview#Uploading_a_Blob

Blobstore upload handler rewrites the request (removing body, adding blobkey) but leaves all other stuff untouched.
The POST mimetype is multipart/form-data, for which GAE/J offers no API to parse. So you need to use 3rd party library to parse parameters - Apache Commons-FileUpload (also as maven artifact).
Use it in your post() handler like this:
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterator = null;
try {
iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
FileItemStream item = iterator.next();
String filename = item.getName();
}
} catch (FileUploadException e) {
// handle the error here
}
Since it's possible to upload multiple files at once you need to iterate through the set of parameters and get out the one you are interested in.

Related

Unable to get the value of form fields when using enctype=multipart/form-data : java servlets

I have written this to upload an image in the specified folder and store the path in database, but when i click on add a blank page is displayed, I have already created all the folders in webcontent.I am using tomcat server:
My upload.jsp code looks something like this:
<form action="Add" method=post enctype="multipart/form-data">
<p>Book name: <input type="text" name="bname" required/></p>
<p>Price:<input type="text" name="bprice" required/></p>
<p>Quantity:<input type="text" name="bqty" required/></p>
<p>Image: <input type="file" name="file" required/></p>
<p>Course: <select name="course">
<option>course 1</option>
<option>course 2</option> <!-- Some more options-->
<input type="submit" value="Add" name="Submit"/></p>
</form>
The Add.java servlet code is:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out=response.getWriter();
String bname=request.getParameter("bname");
String bprice=request.getParameter("bprice");
String bqty=request.getParameter("bqty");
String path="images";
String file=request.getParameter("file");
String course=request.getParameter("course");
if(course.equals("course 1"))
{
path="images/folder1";
}
else if(course.equals("course 2"))
{
path="images/folder2";
}
else
{
path="images";
}
MultipartRequest m=new MultipartRequest(request,path);
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("",user,pass);
PreparedStatement ps=con.prepareStatement("insert into product(bname,course,price,qty,path) values (?,?,?,?,?)");
ps.setString(1,bname);
ps.setString(2,course);
ps.setString(3,bprice);
ps.setString(4,bqty);
ps.setString(5,path+file);
ps.executeUpdate();
}
catch(Exception e)
{
e.printStackTrace();
}
out.print("<p>Product added!</p>");
RequestDispatcher rd=request.getRequestDispatcher("upload.jsp");
rd.include(request, response);
}
I get NullPointer exception.
I read somewhere that instead of using
request.getParameter()
I shoud use
m.getParameter()
I did that and it worked, But that won't solve my problem because my code determines the path based on the value of course from the form.
And also I need to get the filename of the file uploaded, right now I am doing this like this:
String file=request.getParameter("file");
I was trying some sample code and when I used m.getParameter() I managed to get values of all fields except file(I want that coz i want to store the img path in the DB).
When I don't use enctype=multipart/form-data everything works fine (I also get the filename) except the error that content is multipart(That's obvious I know).
ServletRequest#getParameter works only for application/x-www-form-urlencoded data (this encoding is used by default if you don't specify enctype attribute on your form). You can read more information about form content types here.
From the line
MultipartRequest m=new MultipartRequest(request,path);
I am assuming you are using the com.oreilly.servlet library.
In this case, using MultipartRequest#getParameter is a correct way to get the values of fields. In order to get the name of the uploaded file, you can use MultipartRequest#getFilesystemName.
my code determines the path based on the value of course from the form
I am afraid that you won't be able to do this in a clear way with com.oreilly.servlet library. What you could do is move the file by yourself like this:
m.getFile("file").renameTo(new File("newPath"));
Alternatively, you can consider using some other library for dealing with multipart data, such as Apache Commons FileUpload.
You can get both the form fields and the file using cos-multipart.jar.
The following worked for me:
public class FileUploadHandler extends HttpServlet {
private final String UPLOAD_DIRECTORY = "/home/mario/Downloads";
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//fix max file size 500 Mb
int maxFileSize = 500000 * 1024;
int maxMemSize = maxFileSize;
//getting form fields (both text as well as file) (enctype=multipart/form-data)
MultipartRequest mreq = new MultipartRequest(request, UPLOAD_DIRECTORY, maxFileSize);
String uname = mreq.getParameter("username"); //give 'id' in html accordingly
String dateofupload = mreq.getParameter("uploaddate");
//System.out.println(uname);
String NEW_UPLOAD_DIRECTORY = UPLOAD_DIRECTORY;
//get actual file name here //name field in html tag has to be given accordingly
String uploadedfilename = mreq.getFilesystemName("file");
//renaming & moving the file to new location
File newfileloc = new File(NEW_UPLOAD_DIRECTORY + "/" + uploadedfilename);
Boolean uploadresult = mreq.getFile("file").renameTo(newfileloc); //true if success
}
}
This initially saves the file to a location and rename/move it to new location. I could have saved it at the desired location but to do that I need file name, which comes only with the servlet request. But to access filename we need to create 'Multipart' request object. I tried to create two such things, one to access fields and the other to save file. But, cos-multipart.jar has some bugs in handling this.
You might want to consider using Apache commons FileUpload. It helps you handle these kinds of scenarios and handles most of the business logic for you.
When using Apache Commons FileUpload you can parse the request like this:
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List<FileItem> items = upload.parseRequest(request);
You can parse all the individual
// Process the uploaded items
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
try this way:
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MEMORY_THRESHOLD);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(MAX_FILE_SIZE);
upload.setSizeMax(MAX_REQUEST_SIZE); // sets maximum size of request (include file + form data)
String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
for (FileItem item : formItems) {
if (!item.isFormField()) {
//file field
} else {
other form field
}

Saving split uploaded files from POST end up empty

I am trying to fully implement a resumable file upload system in Java. The library I am using is resumable.js which sends chunks of a file to save as .part and then merge them together at the end. When I receive the POST request, in my doPost method I take the request, save it into a HttpServletRequestWrapper and then use that to get all the data I need. However, when saving the files as .part I end up with them being empty and have a size of 0 bytes.
I have checked and it seems that the data is all there, but I can't seem to get the data to save. Is there something that I implemented incorrectly?
Here is a small snippet of the code I use to do this task:
public void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
HttpServletRequestWrapper wrapReq = new HttpServletRequestWrapper(request);
BufferedReader reader = wrapReq.getReader();
/**
* Get some data from the BufferedReader
*/
if(ServletFileUpload.isMultipartContent(wrapReq)){
File mkd = new File(temp_dir);
if(!mkd.isDirectory())
mkd.mkdirs();
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
Iterator<FileItem> iter = upload.parseRequest(request).iterator();
OutputStream out;
out = new FileOutputStream(new File(dest_dir));
while(iter.hasNext()){
try {
FileItem item = iter.next();
IOUtils.copy(item.getInputStream(), out);
logger.debug("Wrote file " + resumableIdentifier + " with chunk number "
+ resumableChunkNumber + " to " + temp_dir);
out.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
}
}
tryCreateFileFromChunks(temp_dir, resumableFileName, resumableChunkSize, resumableTotalSize);
} catch (Exception e) {
e.printStackTrace();
}
}
Where the tryCreateFileFromChunks() method just checks if all the parts are there and merges them. It isn't the problem. The .part files themselves are being stored empty.
So, did I handle this the wrong way? I've been struggling to get this working correctly.
You shouldn't be using HttpServletRequestWrapper, nor be calling its getReader(). The request body can be read only once and you've to choose whether to use getReader() method, or getInputStream() method, or getParameterXxx() methods on the very same request and not mix them.
Apache Commons FileUpload uses internally getInputStream() to parse the request body. But if you've called getReader() or getParameterXxx() beforehand, then Apache Commons FileUpload will get an empty request body.
All with all, to fix your problem, just get rid of wrapReq altogether.
if(ServletFileUpload.isMultipartContent(request)){
// ...
See also:
How to upload files to server using JSP/Servlet?

Upload file from jsp

I am trying to upload multiple files from jsp using below code:
When I execute it from my local machine I am able to upload in the local systems folder.
But when I access the same from remote machine I am expecting that the files should be uploaded to the same machine where my tomcat exist ,but I get error C:\Files\`folder/file not found`.
Please guide.How to upload it in remote machine or where the tomcat resides
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
} else {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.isFormField()) {
} else {
try {
String itemName = item.getName();
File savedFile = new File("C:\\Files\\a.tiff");
item.write(savedFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
This is the path where I want to upload all files C:\\Files\\ of the machine where tomcat is.
Change your file save path to new File("C:\\Files\\"); . Even, still you have any problem, then create one folder with Files name in another drive E or F whatever and change your code like new File("E:\\Files\\"); if you wanna save your file to E drive.
Note: Since, C drive is the primary drive in windows OS, so due to lack of permission, it won't allow to create new file/folder in that drive. So, please try the alternative solution. I mean try to change your file location.
you need to change this new File("C:\\Files\\"); to a foldername on my your remote-server
please take a look at this article
http://www.avajava.com/tutorials/lessons/how-do-i-monitor-the-progress-of-a-file-upload-to-a-servlet.html?page=2
http://www.tutorialspoint.com/jsp/jsp_file_uploading.htm
http://www.caucho.com/resin-3.0/jsp/tutorial/multipart.xtp
http://www.c-sharpcorner.com/UploadFile/0d4935/how-to-upload-files-in-jsp/

FileNotFoundException while saving files in two separate folders

I'm using Spring and Hibernate. I'm uploading images using commons-fileupload-1.2.2 as follows.
String itemName = null;
String files = null;
String itemStatus="true";
Random rand=new Random();
Long randNumber=Math.abs(rand.nextLong());
Map<String, String> parameters=new HashMap<String, String>();
if (ServletFileUpload.isMultipartContent(request))
{
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> items = null;
try
{
items = upload.parseRequest(request);
}
catch (FileUploadException e)
{
mv.addObject("msg", e.getMessage());
mv.addObject("status", "-1");
}
for(FileItem item:items)
{
if (!item.isFormField()&&!item.getString().equals(""))
{
itemName = item.getName();
parameters.put(item.getFieldName(), item.getName());
itemName = itemName.substring(itemName.lastIndexOf(File.separatorChar) + 1, itemName.length());
itemName=randNumber+itemName;
files = files + " " + itemName;
ServletContext sc=request.getSession().getServletContext();
File savedFile = new File(sc.getRealPath("images") , itemName);
item.write(savedFile);
File medium = new File(sc.getRealPath("images"+File.separatorChar+"medium") , itemName);
item.write(medium);
}
}
}
Where itemName is the name of the image file after parsing the request (enctype="multipart/form-data").
The image is first being saved in the images folder and then in the images/medium folder. It's not working causing FileNotFoundException but when I save only one file (commenting out one of them) either this
File savedFile = new File(sc.getRealPath("images") , itemName);
item.write(savedFile);
or this
File medium = new File(sc.getRealPath("images"+File.separatorChar+"medium") , itemName);
item.write(medium);
it works. Why doesn't it work to save both the files in separate folders at once?
I have not used apache commons-fileupload, but the apidoc for the function FileItem#write(File file) says, writing the same item twice may not work.
This method is not guaranteed to succeed if called more than once for
the same item. This allows a particular implementation to use, for
example, file renaming, where possible, rather than copying all of the
underlying data, thus gaining a significant performance benefit.
JavaDoc for DiskFileItem class says,
This method is only guaranteed to work once, the first time it is
invoked for a particular item. This is because, in the event that the
method renames a temporary file, that file will no longer be available
to copy or rename again at a later time.
You might also want to check out this JIRA:
DiskFileItem Jira Issue
References: FileItem JavaDoc, DiskFileItem JavaDoc

Commons File Upload Not Working In Servlet

I have a servlet which is meant to handle the upload of a very large file. I am trying to use commons fileupload to handle it. Currently, the file I am attempting to upload is 287MB.
I set up the FileItemFactory and ServletFileUpload, then set a very large max file size on the ServletFileUpload.
Unfortunately, when I attempt to create a FileItemIterator, nothing happens. The form is set with the correct action, multipart encoding, and for the POST method.
Can anyone assist? doPost() of the servlet is posted below:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ensure that the form is multipart encoded since we are uploading a file
if (!ServletFileUpload.isMultipartContent(req)) {
//throw new FileUploadException("Request was not multipart");
log.debug("Request was not multipart. Returning from call");
}
// create a list to hold all of the files
List<File> fileList = new ArrayList<File>();
try {
// setup the factories and file upload stuff
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(999999999);
// create a file item iterator to cycle through all of the files in the req. There SHOULD only be one, though
FileItemIterator iterator = upload.getItemIterator(req);
// iterate through the file items and create a file item stream to output the file
while (iterator.hasNext()) {
// get the file item stream from the iterator
FileItemStream fileItemStream = iterator.next();
// Use the Special InputStream type, passing it the stream and the length of the file
InputStream inputStream = new UploadProgressInputStream(fileItemStream.openStream(), req.getContentLength());
// create a File from the file name
String fileName = fileItemStream.getName(); // this only returns the filename, not the full path
File file = new File(tempDirectory, fileName);
// add the file to the list
fileList.add(file);
// Use commons-io Streams to copy from the inputstrea to a brand-new file
Streams.copy(inputStream, new FileOutputStream(file), true);
// close the inputstream
inputStream.close();
}
} catch (FileUploadException e) {
e.printStackTrace();
}
// now that we've save the file, we can process it.
if (fileList.size() == 0) {
log.debug("No File in the file list. returning.");
return;
}
for (File file : fileList) {
String fileName = file.getName();
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line = reader.readLine();
List<Feature> featureList = new ArrayList<Feature>(); // arraylist may not be the best choice since I don't know how many features I'm importing
while (!line.isEmpty()) {
String[] splitLine = line.split("|");
Feature feature = new Feature();
feature.setId(Integer.parseInt(splitLine[0]));
feature.setName(splitLine[1]);
feature.setFeatureClass(splitLine[2]);
feature.setLat(Double.parseDouble(splitLine[9]));
feature.setLng(Double.parseDouble(splitLine[10]));
featureList.add(feature);
line = reader.readLine();
}
file.delete(); // todo: check this to ensure it won't blow up the code since we're iterating in a for each
reader.close(); // todo: need this in a finally block somewhere to ensure this always happens.
try {
featureService.persistList(featureList);
} catch (ServiceException e) {
log.debug("Caught Service Exception in FeatureUploadService.", e);
}
}
}
It was an incredibly stupid problem. I left the name attribute off of the FileUpload entry in the GWT UiBinder. Thanks for all of the help from everyone.
Are the only request parameters available File items? Because you may want to put in a check:
if (!fileItemStream.isFormField()){
// then process as file
otherwise you'll get errors. On the surface of things your code looks fine: no errors in the Tomcat logs?
You need to add enctype='multipart/form-data' in html form

Categories

Resources