I am building a desktop app using javafx, I am downloading a file around 500 MB using ftp. I am choosing the download location using DirectoryChooser but after choosing the directory my application hang and doesn't response.
Though the file is downloaded.
here is my code:-
try {
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
success = ftpClient.changeWorkingDirectory(PATH + preset + "/" + file_to_download + offset);
System.out.println("Download Path:-" + PATH + preset + "/" + file_to_download + offset);
if (!success) {
System.out.println("Could not changed the directory to RIBS");
return;
} else {
System.out.println("Directory changed to RIBS");
}
FTPFile[] files = ftpClient.listFiles();
for (FTPFile file : files) {
if (file.getName().contains(".zip")) {
dfile = file.getName();
}
}
DirectoryChooser dirChooser = new DirectoryChooser();
File chosenDir = dirChooser.showDialog(tableView.getScene().getWindow());
System.out.println(chosenDir.getAbsolutePath());
OutputStream output;
output = new FileOutputStream(chosenDir.getAbsolutePath() + "/" + dfile);
int timeOut = 500;
ftpClient.setConnectTimeout(timeOut);
if (ftpClient.retrieveFile(dfile, output) == true) {
downloadButton.setDisable(true);
}
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
How can I improve this??
You are performing your download on the application thread which blocks the UI. Have a look at the documentation about JavaFX concurrency.
https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm
Related
I use netty offical example HttpStaticFileServerHandler as file server, but when I download file from server I met a problem, the mp4 file I download from server is not complete and can't display.
https://github.com/netty/netty/blob/4.1/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
And here is my client code:
FileOutputStream fos = null;
try {
URL website = new URL("http://localhost:8090/export/App/***.mp4");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
fos = new FileOutputStream("/Users/mine/***.mp4");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
} catch (Exception e) {
System.out.println("error msg:\n" + e);
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException ioe) {
System.out.println("fos close fail:\n" + ioe);
}
}
Make sure you close your FileOutputStream using fos.close().
Failing to do so means that only part of the data will be written, and that other programs may experience problems when accessing the file.
Another thing you could check is viewing the filesize of the file, those should match at both sides, if the file is way too small, open it with an text editor, and view the contents to check for clues.
I solved this problem. I find the RandomAccessFile is not closed in correct time.
Here is the change:
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException ignore) {
sendError(ctx, NOT_FOUND);
return;
}
...
sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
#Override
public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
if (total < 0) { // total unknown
System.err.println(future.channel() + " Transfer progress: " + progress);
} else {
System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);
}
}
#Override
public void operationComplete(ChannelProgressiveFuture future) {
System.err.println(future.channel() + " Transfer complete.");
raf.close();// close raf when transfer completed
}
});
I'm trying to download a file which I have on a server.
If I run my application on local everything works properly and I can download the file. Also, I can download the file from a browser or Windows File explorer.
However, when I upload my application to my server, I can't get the file.
try {
uri = "\\DEVDOCSERVER\DOCUMENTS\sample.xml";
if(uri.contains(".") ) {
String extension = uri.substring(uri.lastIndexOf("."));
File file = new File(uri);
if(file!=null)
logger.error("file size: " + file.length());
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
String fileName = getFileName(uri);
logger.error("file name: " + fileName);
String contentType = "application/octet-stream";
response.setContentType(contentType);
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
response.setContentLength((int) file.length());
ServletOutputStream out = null;
try {
FileInputStream input = new FileInputStream(file);
byte[] buffer = new byte[1024];
out = response.getOutputStream();
int i = 0;
while ((i = input.read(buffer)) != -1) {
out.write(buffer);
out.flush();
}
if(input!=null)
logger.error("file input: " + input.toString());
FacesContext.getCurrentInstance().responseComplete();
} catch (IOException err) {
err.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException err) {
err.printStackTrace();
}
}
}
} catch (InternacionalizacionFwException e) {
e.printStackTrace();
}
When I check log, I get next error: (No such file or directory) and the file size is 0
Which Server - Linux, Windows etc. In Linux env its path should be set to forward slash e.g /opt/something/yourfile. Also please log the file path to know in run time location for file you are looking which will help you understand the cause of issue.
Finally, I solved my problem changing the file path depending if I'm working on Windows or Linux.
I also moved the file to another folder because it seemed that I hadn't permissions in the folder I was.
And I had to change the way I was reading the file, because I was getting and error "Error: Network Error" when I was downloading file
Now I'm reading with apache commons:
FileUtils.copyFile(file, response.getOutputStream());
My requirement is to copy the file from local machine(Windows) to unix serevr. I have the code which was working fine with some Mbs data. i am using jsch lib to connect and to transfer.
But now i have to transfer the files of 1GB, 2Gb or may be 5GB.
When i am using the same approach.
Its getting failed. Its stucking at
channelsftpObj.put(from,to);
and then exception is "faliure". Nothing else coming in exception.
May i know the reason or how can i transfer these files?
private boolean executeCommand (String localDir, String remoteDir, String fileList, String actionFlg) {
boolean boolError = false;
String localPath, destinationPath;
ChannelSftp channelSFTPObj = (ChannelSftp) channelObj;
for (int i = 0; i < filelistArr.length; i++ ) {
localPath = localDir + "/" + filelistArr[i];
destinationPath = remoteDir + "/" + filelistArr[i];
try {
if (actionFlg.toLowerCase() == "upload") {
channelSFTPObj.put (localPath, destinationPath);
System.out.println ("Uploaded " + filelistArr[i] + " to " + remoteDir);
}
}
catch (SftpException e) {
System.out.println(e);
boolError = true;
}
}
channelSFTPObj.exit();
return boolError;
}
localDir is my path of my local system, remoteDir is the server path.
Successfully connected to the server.
In my Web methods application in Java I'm selecting a file and downloading it.When the download window closes I made the control to be directed back to parent page. I implemented it by creating an IPortletURL calling BasePortletPageBean.createRenderURL(),setted its base URL to a portlet's alias name where I want to redirect. Then called FacesContext redirect method. It worked fine in Web methods 8.0 and I had developed it in a Windows XP machine. Now I imported the same project to a web methods 8.2 installed Windows 7 machine, but now its not working. Kindly help me.
public String downloadMaster() {
List<Object> selectedRows = getFnamesProvider2().getSelectedRows();
if (getFnamesProvider2().getSelectedRows() != null
&& getFnamesProvider2().getSelectedRows().size() != 0) {
for (Iterator iterator = selectedRows.iterator(); iterator
.hasNext();) {
com.webmethods.caf.FileNames details = (com.webmethods.caf.FileNames) iterator
.next();
System.out.println("Iterator Output!!!!!!!!!!!!!!!!!!!!!!!"
+ details.toString());
FileInputStream fileInputStream = null;
OutputStream out = null;
try {
String filename = "C:/SoftwareAG/MWS/Projects/"
+ getProjName() + "/"
+ session.getAttribute("folder").toString()
+ "/search/" + details.getFileName();
if (response == null) {
response = PortalServlet.getCurrentResponse();
setResponse(response);
}
if (response.getContentType() == null
|| (!(response.getContentType()
.equalsIgnoreCase("APPLICATION/DOWNLOAD")))) {
if (response == null) {
response = PortalServlet.getCurrentResponse();
}
getResponse().setContentType("APPLICATION/DOWNLOAD");
}
response.setHeader("Content-Disposition", "attachment"
+ "filename=" + details.getFileName());
File fileToDownload = new File(filename);
fileInputStream = new FileInputStream(fileToDownload);
response.setContentLength(fileInputStream.available());
out = response.getOutputStream();
response.setHeader("Content-Disposition",
"attachment;filename=" + details.getFileName());
int i;
while ((i = fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
out.close();
List<Object> selRows = getFnamesProvider2()
.getSelectedRows();
} catch (Exception e) // file IO errors
{
e.printStackTrace();
} finally {
try {
IPortletURL renderURL = createRenderUrl();
renderURL.setBaseURL("/kneipp.NewProject");
System.out.println("::::::renderURL::::::" + renderURL);
getFacesContext().getExternalContext().redirect(
renderURL.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
return OUTCOME_OK;
}
Make sure you are always using the full paths, Webmethods 8.2 needs the full path for urls or any ressources like images also.
This might be a cause of your problem.
well this is a strange one.
The first save attampt usually works (1 more try max).
but in a heavy load (many saves in a row) the saved file disappears.
if uncommenting the "Thread.sleep" the error is captured otherwise the validation passes succesfully
public void save(Object key, T objToSave) throws FileNotFoundException, IOException {
IOException ex = null;
for (int i = 0; i < NUM_OF_RETRIES; i++) {
try {
/* saving */
String filePath = getFilePath(key);
OutputStream outStream = getOutStream(filePath);
ObjectOutputStream os = new ObjectOutputStream(outStream);
os.writeObject(objToSave);
os.close();
/* validations warnings etc. */
if (i>0){
logger.warn(objToSave + " saved on attamped " + i);
/* sleep more on each fail */
Thread.sleep(100+i*8);
}
//Thread.sleep(50);
File doneFile = new File(filePath);
if (! (doneFile.exists())){
logger.error("got here but file was not witten to disk ! id was" + key);
throw new IOException();
}
logger.info("6. start persist " + key + " path=" + new File(filePath).getAbsolutePath() + " exists="+doneFile.exists());
return;
} catch (IOException e) {
logger.error(objToSave + " failed on attamped " + i);
ex = e;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
throw ex;
}
It is not a java writers issue.
I was not using threads explicitly but in my test I was deleting the folder i was saving to using: Runtime.getRuntime("rm -rf saver_directory");
I found out the hard way that it is asynchronous and the exact delete and create time was changing in mili-seconds.
so the solution was adding "sleep" after the delete.
the correct answer would be using java for the delete and not making a shortcuts ;)
Thank you all.