YUI Uploader with Java back-end - java

I am trying to use the (flash based) YUI Uploader with a Java (Spring-based) back-end.
The typical way of uploading files in the Java Servlet world is to set the ENCTYPE='multipart/form-data' on the HTML form requesting the file from the user. With the right server side APIs (i.e. Commons FileUpload), it is possible to get the file on the server.
But I am stymied by how to achieve this with the YUI Uploader. I am able to reach the Java controller, and I am even able to extract the custom post values. But I have no idea how to extract the binary file data out of the request.
Has anyone out had any luck with a YUI uploader with a Java back-end?

To answer my own question, and to make a long story short, this snippet of code did the trick:
#Controller
#RequestMapping("/FileUploadController")
public class FileUploadController {
#RequestMapping(method = RequestMethod.POST)
protected ModelAndView onSubmit(HttpServletRequest request) throws Exception{
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> /* FileItem */ items = upload.parseRequest(request);
for (FileItem fileItem : items) {
if (fileItem.isFormField()) {
// processFormField(fileItem);
} else {
File uploadedFile = new File("/tmp/junk/" + fileItem.getName());
fileItem.write(uploadedFile);
}
}
return new ModelAndView("index");
}
}
This example uses Spring, but you should be able to do exactly the same as long as you have HttpServletRequest object.

Related

Rest Controller: uploading file using HttpServletRequest through Swagger UI

I wonder if it is possible to show the input file to select in my Swagger UI when exposing the API.
I confirm that it is working perfectly when defining the endpoint as following:
public ResponseEntity<String> upload(#RequestPart MultipartFile file)
There is no doubt to show the file chooser when using MultipartFile.
And as I would like to upload big files, I have to use HttpServletRequest instead in order to upload the file as a stream. The endpoint will be then like:
public #ResponseBody Response<String> upload(HttpServletRequest request) {
// 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()) {
String filename = item.getName();
// Process the input stream
OutputStream out = new FileOutputStream(filename);
IOUtils.copy(stream, out);
stream.close();
out.close();
}
}
return new Response<String>(true, "Success", "");
}
The endpoint is working well using a curl command. But unfortunately when using the Swagger UI, I am not able to show the file chooser.
Does anyone faced the same case or knows if Swagger supports this feature?

Writing unit test for file uploader in Junit/Mockito

I am trying to write a unit test for following component to upload file:
#Component("uploader")
public class FileUploader {
public List<FileItem> processFileUploadRequest(HttpServletRequest request) throws FileUploadException {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletContext servletContext = request.getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
ServletFileUpload upload = new ServletFileUpload(factory);
return upload.parseRequest(request);
}
}
I have written unit test using junit/mockito like following:
#Test
public void testProcessFileUploadRequestSuccess() throws FileUploadException {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
ServletContext servletContext = Mockito.mock(ServletContext.class);
Mockito.when(request.getServletContext()).thenReturn(servletContext);
Mockito.when(servletContext.getAttribute("javax.servlet.context.tempdir")).thenReturn(this.servletTmpDir);
Assert.assertNotNull(fileUploader.processFileUploadRequest(request));
}
I am getting the following error:
org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is null
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:947)
...
Can anyone please give any clue regarding this? Thank you.
This error ...
the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is null
... is a result of your HttpServletRequest not having a multipart content type.
You can fix this by adding the following line to your test case:
Mockito.when(request.getContentType()).thenReturn("multipart/form-data; boundary=someBoundary");
Ona side note: your question (specifically, this part: #Component("uploader")) suggests that you are using Spring. If so, then perhaps your file upload code could be more easily tested using Spring's MockMvcRequestBuilders#fileUpload(String, Object...) to return a MockMultipartHttpServletRequestBuilder. Something like this:
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload")
.file(aFile)
.andExpect(status().is(200))
.andExpect(content().string("..."));

how to create excel sheet without return ModelAndView?

hi am create excel sheet using extends AbstractExcelView i write following code
public ModelAndView exportToExcel(HttpServletRequest request, #RequestParam Map<String, ? extends Object> params, ShipmentDetailsSearchInput shipmentDetailsInputType) throws ParseException
{
Map<String, Object> excelMap = new HashMap<String, Object>();
return new ModelAndView("ExcelReport", UIErrorMessages.DATA, excelMap);
}
i wont to get Ajax response that file download success in Extjs Ajax response because ModelAndView Not Give any response in submit ajax call.
how to we can write restful excel-download component without modeandview in spring 3
If you want to create dynamic excel file sheet then you can use Apache POI. You can create ,update and modify excel sheet.
I am using Apache POI to generate an excel file and filling it.
More details can be found here, example link and another example link.
Please note you don't have to use Ajax and can directly map a GET request to the method exportToExcel.
To avoid return ModelAndView object, you can directly write the generated file into response stream.
You will have to set ContentType and HttpServletResponse header to appropriate format,
as show below:
public void exportToExcel(HttpServletRequest request, #RequestParam Map<String, ? extends Object> params, ShipmentDetailsSearchInput shipmentDetailsInputType,
HttpServletResponse response) throws ParseException
{
// Map<String, Object> excelMap = new HashMap<String, Object>();
// return new ModelAndView("ExcelReport", UIErrorMessages.DATA, excelMap);
String fileName = "RandomFile";
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "vnd.ms-excel"));
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
//method to create Workbook
Workbook book = createFileAndFillDetails();
try {
book.write(response.getOutputStream());
}
catch (IOException e) {
//Handle error
}
}
If you have to use Ajax there are no direct solutions. The choices you are left with are :
1) Using a hidden frame as mentioned in How to download file from server using jQuery AJAX and Spring MVC 3
2) Redirect the browser
3) Don't use ajax at all, because ajax/jquery is not going to be useful to handle this scenario. A url with GET request offers easy approach as mentioned in the other solution proposed.
If I undestand correctly your question, you want to create an excel spreadsheet when an asynchronous call is made to your controller (so via AJAX).
First of all, I don't think it's a good idea to download file via ajax call. If your problem is a long time to generate your excel spreadsheet, I suggest you to generate it asynchronously (in a separate thread for example) and than to download the generated file via a classical GET request.
I'm doing something similar in a web application that generate a large CSV file. I'm using this simple method to get the generated file:
#RequestMapping(value = "/file", method = RequestMethod.GET)
public void getFile(
#RequestParam(value = "token", required = false) String token,
HttpServletResponse response) throws Exception {
// my logic...
String formattedDataString = exportTask.getResults());
response.setHeader("Content-Disposition", "attachment; filename=\""
+ exportTask.getExportFileName() + "\"");
response.setContentType("text/plain; charset=utf-8");
IOUtils.copy(
new ByteArrayInputStream(formattedDataString.getBytes()),
response.getOutputStream());
response.flushBuffer();
}
}
In my page I have a simple link like this:
<c:url var="fileUrl" value="results/file">
<c:param name="token" value="${token}" />
</c:url>
<a href='<c:out value="${fileUrl}" />'>Get File</a>
In my case the token param identify the generated file, that is stored in the local DB.
However, if you still want to use ajax, I suggest you to take a look to #ResponseBody annotation.

Retrieve an Image from a POST request

I am trying to send a picture to my java servlet (hosted on amazon ec2) to later transfer it to amazon s3 and wonder how to retrieve the Image from the post request.
Upload Code
The request is sent through iOS RestKit API like this (pic.imageData is a NSData type):
RKParams* params = [RKParams params];
[params setValue:pic.dateTaken forParam:#"dateTaken"];
[params setValue:pic.dateUploaded forParam:#"dateUploaded"];
[params setData:pic.imageData MIMEType:#"image/jpeg" forParam:#"image"];
[RKClient sharedClient].username = deviceID;
[RKClient sharedClient].password = sessionKey;
[RKClient sharedClient].authenticationType = RKRequestAuthenticationTypeHTTPBasic;
uploadPictureRequest = [[RKClient sharedClient] post:kUploadPictureServlet params:params delegate:self];
Parsing Code Stub
This is how I parse the other 2 parameters on the Java servlet:
double dateTaken = Double.parseDouble(req.getParameter("dateTaken"));
double dateUploaded = Double.parseDouble(req.getParameter("dateUploaded"));
Question
The question is: how do I retrieve and parse the image on my server?
Servlet 3.0 has support for reading multipart data. MutlipartConfig support in Servlet 3.0 If a servelt is annotated using #MutlipartConfig annotation, the container is responsible for making the Multipart parts available through
HttpServletRequest.getParts()
HttpServletRequest.getPart("name");
References:
Servlet 3.0 File Upload handing files and params
Servlet 3.0 File upload Example
Something along the lines of this, using Apache Commons FileUpload:
// or #SuppressWarnings("unchecked")
#SuppressWarnings("rawtypes")
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
final FileItemFactory factory = new DiskFileItemFactory();
final ServletFileUpload upload = new ServletFileUpload(factory);
try {
final List items = upload.parseRequest(request);
for (Iterator itr = items.iterator(); itr.hasNext();) {
final FileItem item = (FileItem) itr.next();
if (!item.isFormField()) {
/*
* TODO: (for you)
* 1. Verify that file item is an image type.
* 2. And do whatever you want with it.
*/
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
Refer to the FileItem API reference doc to determine what to do next.

Upload word document

I need to extract text from the word document uploaded by the user. I got the code to extract words from a document located on my m/c. But my requirement is to allow users to upload their own document using the upload button & read that document(I dont need to save that document). Can you please suggest me how to go about this? I need to know what all need to happen after clicking the upload button.
When the user uploads their file, grab the associated InputStream and store it to a variable, like inputStream. Then just take the example code, and replace this line:
fs = new POIFSFileSystem(new FileInputStream(filesname));
...with something like:
fs = new POIFSFileSystem(inputStream);
Should be simple enough, assuming that you already have a Servlet in place to handle the upload.
Edit:
Here are the basics of how the servlet could work, assuming that you are using commons-fileupload to parse the upload:
public class UploadServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 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);
//this assumes that the uploaded file is the only thing submitted by the form
//if not you need to iterate the list and find it
FileItem wordFile = items.get(0);
//get a stream that can be used to read the uploaded file
InputStream inputStream = wordFile.getInputStream();
//and the rest you already know...
}
}

Categories