Java outputstream, trigger file download before all data retrieved from db - java

Im trying to wrap my head around Java Out/Inputstreams, closing and flushing. I have a situation where I want to create a file using Apache POI with data from a server. I would like the file to start downloading as soon as I retrieve the first record from the DB(Show the file at the bottom of the browser has started to download).
public void createExcelFile(final HttpServletResponse response,
final Long vendorId) {
try {
// setup responses types...
final XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
final XSSFSheet sheet = xssfWorkbook.createSheet("sheets1");
// create file with data
writeExcelOutputData(sheet, xssfWorkbook);
xssfWorkbook.write(response.getOutputStream());
xssfWorkbook.close();
}
catch (final Exception e) {
LOGGER.error("Boom");
}
The above code will perform a file download no problem, but this could be a big file. I go off getting the data(around 20/30s) and then after that the download begins < no good...
Can I achive what I need or whats the best approach, thanks in advance
Cheers :)

Reasons could be as following:
maybe there is a read/write timeout with your http server, then if the process gets lengthy or becasue of low-bandwidth, so the connection will be closed by the server.
make sure the process(the excel work) gets completely done, maybe there would be an error/exception during work.
The solution of Jorge looks very promising. User need once request for a file, then server would do the work in background and then either user check the work process and download the file if ready, or server informs the user by email, web notification, etc...
Also you would keep the file in the server in a temp file for a while, and if the connection gets interrupted, server would respond the generated file partial(omit the bytes sent, like normal file download)
Keeping a connection alive to do a lengthy work is not very logical.
Again, if the file gets ready fast(really fast) for download/stream, and the download interrupts, if could be becasue of read/write timeout by server, or a very bad network.

Related

How to continuously read an online/web file in java?

I am making a simple text-only instant messenger in java. The way that it currently works is that all the messages are put into an online text file by sending a php file a request (I know this is bad for security, but this is just to learn how to do web-connected apps in java.)
Currently, I am continually fetching the entire contents of the messages.txt file and placing them into my JTextPane like this:
while(true) {
URL url = new URL("{path to text file}");
InputStream in = url.openStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String conversation = s.hasNext() ? s.next() : "";
textPane.setText(conversation);
}
But when the conversation becomes long enough, it lags as it is fetching 100kb+ files constantly from a web server.
What I want to happen is to only read the changes to the file so that it doesn't lag and max out my internet connection by requesting enourmous amounts of plain text files. I don't want to just make it run every 2 seconds because it's an instant messenger, no delays.
How would I go around only fetching the changes to the file and adding them to the text pane?
Can you push the file contents to another file once it crosses a certain threshold. This will ensure that you operate upon a smaller file.
Instead of contacting url directly you could place some server side script that would call the file
You could (as a client) provide the server script the last line / message identifier and the server could respond with new messages that have been added after the message id that the client has provided. In addition it could send the new last message id
With this approach the server side script doesnt even need to read itself the whole file and instead can immediately skip to the required line if message id contains the information about the line in the log file
Of course this approach is really far from real scenarios but its ok for learning IMO

How to interrupt the loading of a webpage?

I know the title is a bit confusing. I will describe my task:
Now I'm writing a webpage, which allow me to download some data or do some other stuff. The front end is jsp and the back end is java. So every time when I do something on this page(e.g. sort the data or download the data), a request will be sent to java and after data processing the .jsp page will be refreshed and loaded again(of cause after sorting it should be refreshed). But I just found that if I download a data with the following code, the refreshing will be interrupted:
OutputStream out = response.getOutputStream(); // response is HttpServletResponse
doSomeOutput(out); // Just write something into OutputStream
out.flush(); // **PAY ATTENTION**. The refreshing is interrupted here!
out.close();
When I was debugging, the page was keeping loading until the third line. And then the page was not refreshed and the data was download.
I hope you can understand what I'm talking about:(
So now I have 2 questions: 1. How can I let the process keep working after out.flush();? 2. In my task I need the same behavior(the process is interrupted) in some other modules, but there's nothing to be download. So how can I interrupt the process besides out.flush();?
Thank you guys!!
1)
https://docs.oracle.com/javaee/5/api/javax/servlet/ServletResponse.html#getOutputStream%28%29
"Calling flush() on the ServletOutputStream commits the response"
as i understand this: active refreshing is stopped, as we got main part of data. But you would be able to send data even after commit. So you can keep working after flush.
Set headers are also sent with flush.
2) Pls explain more thoroughly. call "return", or close?

Why is this URL not opened from Play! Framework 1.2.4?

I have a URL in my Play! app that routes to either HTML or XLSX depending on the extension that is passed in the URL, with a routes line like :-
# Calls
GET /calls.{format} Call.index
so calls.html renders the page, calls.xlsx downloads an Excel file (using Play Excel module). All works fine from the browser, a cURL request, etc.
I now want to be able to create an email and have the Excel attached to it, but I cannot pull the attachment. Here's the basic version of what I tried first :-
public static void sendReport(List<Object[]> invoicelines, String emailaddress) throws MalformedURLException, URISyntaxException
{
setFrom("Telco Analysis <test#test.com>");
addRecipient(emailaddress);
setSubject("Telco Analysis report");
EmailAttachment emailAttachment = new EmailAttachment();
URL url = new URL("http://localhost:9001/calls.xlsx");
emailAttachment.setURL(url);
emailAttachment.setName(url.getFile());
emailAttachment.setDescription("Test file");
addAttachment(emailAttachment);
send(invoicelines);
}
but it just doesn't pull the URL content, it just sits there without any error messages, with Chrome's page spinner going and ties up the web server (to the point that requests from another browser/machine don't appear to get serviced). If I send the email without the attachment, all is fine, so it's just the pulling of the file that appears to be the problem.
So far I've tried the above method, I've tried Play's WS webservice library, I've tried manually-crafted HttpRequests, etc. If I specify another URL (such as http://www.google.com) it works just fine.
Anyone able to assist?
I am making an assumption that you are running in Dev mode.
In Dev mode, you will likely have a single request execution pool, but in your controller that send an email, you are sending off a second request, which will block until your previous request has completed (which it won't because it is waiting for the second request to respond)...so....deadlock!
The resaon why external requests work fine, is because you are not causing the deadlock on your Play request pool.
Simple answer to your problem is to increase the value of the play.pool in the application.conf. Make sure that it is uncommented, and choose a value greater than 1!
# Execution pool
# ~~~~~
# Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode.
# Try to keep a low as possible. 1 thread will serialize all requests (very useful for debugging purpose)
play.pool=3

Processing a large file with a web service

I have web service method that is supposed to process a very large file and output several files to the server. However, this web service will just timeout and there will be no way for the invoker to get the CREATED status. I am just wondering whether there is a way to run the processing job (starting a new thread or something) and return the status without waiting for the process to be done.
public Response processFile(InputStream inputStream){
//I want to process the file here
//but I dont want the invoker to wait for that process to finish
//I just want the response to be returned right away
return Response.status(Response.Status.CREATED).build();
}
The file comes from the input stream, right? So if you'll send back a CREATED status (effectually closing the connection) you might sever the connection before you receive the entirety of the input file?
That's what i thought anyways... In which case you'll just want to set the timeout to a lengthier value.
If that's not the case, then i guess it would be fine to start a new thread, process everything there in good time and send back the CREATED status.

Image not deleted even if file.delete() method is called

I need to send an email along with an embedded image. Once the email has been sent, the image in the application server should be deleted immediately. The problem I'm facing is, after the email is sent, the control goes method which contain,
File file = new File("../bar.jpeg")
if(file.exists()){
file.delete();
System.out.println("Barcode Image Deleted");
}
It's printing "Barcode Image Deleted". But, the image is not deleted and is still present in the same location. I'm using multipart to attach the image to the email.
Why is it not getting deleted?
Are you using javax.mail?
If so, you'll need to wait till the mail has finished being sent, which you find out about by registering a TransportListener.
This also means you won't be able to use the static Transport.send() methods, but will have to construct and clean up your own session and transport.
I'm trying to remember details from a while ago... I think the DataHandler or DataSource don't close the input stream when they've finished reading it, so you need to keep a reference to it and close it yourself before you can delete the underlying file.
The File.delete method returns a boolean which indicates whether the deletion was successful.
It could be that the file deletion is not being successfully performed due to not having permissions to delete the file.
File.delete() returns a true/false condition. Try checking the return condition of delete to see if the system is actually reporting the file as deleted.
Firstly, File.delete() returns a boolean if it successfully deletes a file. Check that value and at least log it.
If it is not being deleted, then I would guess that either
the file is currently open for reading and the OS won't let you delete it until it is closed. Possible your mail software? My guess is that the mail software does not try to base64 encode the image (for inclusion in the message) until it is actually sending the message...and/or does not stop reading it until the mail is sent.
the java process does not have permissions to delete the file

Categories