Here's what I'm doing. I want to upload multipart file via Ajax to my Spring web app. When the server receives the POST request, it creates a ticket number in the database. It then starts a thread that handles the actual file upload. The server then returns the ticket number.
I am using the CommonsMultipartResolver to handle the request and I have set the resolveLazily flag to true so that the Multipart isn't resolved right away.
So here's something along the lines of what I have
@Controller
public class myController{
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public String upload(MultipartHttpServletRequest request, String fileName){
String ticket = dao.createUploadTicket(fileName);
Runnable run = new Runnable(){
@Override
public void run(){
dao.writeUpdate(ticket, "Getting data from request");
final MultipartFile file = request.getFile("theFile");
dao.writeUpdate(ticket, "Multipart file processed");
try {
dao.writeUpdate(ticket, "Saving file to disk");
file.transferTo(new File("/myDirectory"));
dao.writeUpdate(ticket, "File saved to disk");
}
catch(Exception e){
dao.writeUpdate(ticket, "File upload failed with the exception " + e.toString());
}
}
};
Thread t = new Thread(run);
t.start();
return ticket;
}
}
So the point here is that the ticket number can be used to get the progress updates. Say a large file is being uploaded. The client that made the file upload POST (say in this instance an Ajax request) can do it asynchronously and get back a ticket number. The client can the use that ticket number to determine the stage of the file upload and display information in another page.
One other use is that I can have an HTML page that makes a request to the server for all ticket numbers, then shows a "live" view of all the file uploads that are taking place on the server.
I haven't been able to get this to work because as soon as the controller returns, Spring calls cleanupMultipart() in the CommonsMultipartResolver. Since the resolveLazily flag is set to false, when cleanupMultipart() is called, it will begin to resolve and initialize the multipart files. This leads to a race condition between the call to "request.getFile("theFile");" in the runnable and the cleanupMultipart() call eventually leading to an exception.
Anyone have any ideas? Am I breaking some kind of HTTP contract here by wanting to do back-end asynchronous file handling.
This feature allows you to upload and remove files asynchronously. When multiple files are chosen in Asynchronous upload,files will be uploaded one by one to the server. User interaction with the page will not be interrupted at the time of upload. User can also remove the file even after uploading.
With the server running, you need to open a browser and visit http://localhost:8080/ to see the upload form. Pick a (small) file and press Upload. You should see the success page from the controller. If you choose a file that is too large, you will get an ugly error page.
By default, Spring uses a SimpleAsyncTaskExecutor to actually run these methods asynchronously. But we can override the defaults at two levels: the application level or the individual method level.
Spring Boot uses a SimpleAsyncTaskExector to run an async method. This Executor runs by default and it can be overridden at two levels- at the individual method levels or at the application level. 3. Add @Async Annotation to a service Method for performing thread's task without interrupting another parallerl process.
HTTP request is already executed in its own thread, and client can make few request in parallel, asynchronously. So you don't need to start a new thread. Just save/process file as usual, in main thread. Just make 'async file upload' only on client side.
Also, you should send http response only when you've processed the input. I mean you can't read input header, make a http response, and continue reading data from the browser. Consume input -> Process it -> Send output, that how HTTP 1/1.1 protocols works.
If you need a ticket number to send to upload, you could create it before actual uploading, by using a two step upload, like:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With