I am working on a simple piece of java code for transferring a file from an HTTP site to the local machine. All works well and I can download without any problem. The code below updates my progress bar status during the download also without any problem.
My Question: How do I detect that the FTP site is no longer available/connected wile downloading? A separate thread monitoring the ftp isAvailible () and isConnected () methods always returns true even with the network switched off?
Please see code below:
// Disable the download button
BTNdownload.setText("Downloading...");
BTNdownload.setEnabled (false);
// Create a instance of the FTP client
ftpClient = new FTPClient();
// Setup the FTP client
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// Create a file in destination folder
output = new File(destination);
// Request the download file size
ftpClient.sendCommand("SIZE", origin);
// Get the size of the file
String size = ftpClient.getReplyString().split(" ") [1].trim();
total = Long.parseLong(size);
// Set the JProgressBar limits
JPBprogress.setMinimum(0);
JPBprogress.setMaximum((int) total/1024);
// Enable the progress bar
JPBprogress.setEnabled(true);
// Create a input stream from the remote file
stO = ftpClient.retrieveFileStream(origin);
// Create a output stream to the output file
OutputStream stD = new BufferedOutputStream(new FileOutputStream(output));
// Add a progress listener to the copy process
org.apache.commons.net.io.Util.copyStream(stO, stD, ftpClient.getBufferSize(),
org.apache.commons.net.io.CopyStreamEvent.UNKNOWN_STREAM_SIZE,
new org.apache.commons.net.io.CopyStreamAdapter() {
public void bytesTransferred(long totalBytesTransferred,
int bytesTransferred,
long streamSize) {
// Update the progress bar
JPBprogress.setValue((int) totalBytesTransferred/1024);
}
});
// Close the input & output stream
stO.close();
stD.close ();
// Send the FTP completed command
ftpClient.completePendingCommand();
// Close the connection
ftpClient.abort();
// Set the update button enabled
BTNinstall.setEnabled(true);
You can use sendNoOp() to ping the ftp server in order to keep the connection alive on a long running download.
Related
I am trying to FTP a text file to mainframe using java. I am able to create a member in PDS using below code.
//Function to FTP the report
public void sendReport() throws IOException
{
FTPSClient ftp = null;
InputStream in = null;
String protocol="TLS";
//Connecting to mainframe server for ftp transfer
ftp = new FTPSClient(protocol);
ftp.connect(hostname);
ftp.login(user,password);
ftp.execPBSZ(0);
ftp.execPROT("P");
ftp.enterLocalPassiveMode();
ftp.setFileType(FTP.ASCII_FILE_TYPE);
int reply = ftp.getReplyCode();
System.out.println("Received Reply from FTP Connection:" + reply);
if (FTPReply.isPositiveCompletion(reply))
System.out.println("Connected To Mainframe");
else
System.out.println("Not connected to Mainframe..Check ID or Password");
//Setting mainframe PDS for reports
boolean success = ftp.changeWorkingDirectory("***Mainframe Directory***");
if (success)
System.out.println("Successfully changed PDS.");
else
System.out.println("Failed to change PDS. See Mainframe's reply.");
//Sending Report to mainframe PDS
File f1 = new File(dkReportName);
in = new FileInputStream(f1);
boolean done = ftp.storeFile("DKI"+dkReportName.substring(14,18), in);
in.close();
if (done)
System.out.println("FILE FTP SUCCESSFUL");
else
System.out.println("FILE FTP NOT SUCCESSFUL");
ftp.logout();
ftp.disconnect();
}
user,password and hostname variables are being set in appContext.xml.
However, I want to create a PS dataset.
Could anyone please suggest a way of doing it.
Based on your question, this is for the MVS file space and not USS.
When creating a dataset with FTP you need to give the host some information about files size, attributes, etc.
This page on IBM's website outlines a list of commands that you can execute to setup for the transfer. The basic sequence would be something like:
site cyl
site pri=5
site sec=5
site recfm=fb
and you can combine more than one command on a line:
site lrecl=80 blksize=3120
Execute these commands before the transfer and the file should be allocated with your desired characteristics.
Based on your coding example here is a sample that should work:
ftp.sendCommand("site",
"cyl pri=5 sec=5 recfm=fb filetype=seq lrecl=80 blksize=3120");
I wrote an application that listens for status messages from a robot. I have an open Socket connection to the robot. The robots sends constantly status messages which I read ( and parse ) to find out when the robot is done with his current task.
/**
* Listens on the Socket for RobotStateMessage (RSM). A RSM has messagetype 16 at byte[4]. The constructor of the RobotStateMessage class
* throws an exception when the message is found to be corrupt. If that happens the method waits for the next uncorrupted message.
*
* #param command the robot state message is added to the command
* #throws IOException
* #throws GeneralURMessage_Parse_Exception
* #throws TimeExpired_Exception
*/
public void executeRobotStateCommand(RobotStateCommand command) throws IOException, RobotStateMessage.GeneralURMessage_Parse_Exception, TimeExpired_Exception {
byte[] data = new byte[3000];
boolean run = true;
RobotStateMessage message = null;
long momentToQuit = System.currentTimeMillis() + 5000;
while (run) {
if (System.currentTimeMillis() > momentToQuit) {
throw new TimeExpired_Exception(5000);
}
ur_in.read(data);
int type = data[4];
if (type == 16) {
run = false;
try {
// contructor of RobotStateMessage parses the data
message = new RobotStateMessage(data);
} catch (RobotStateMessage.CorruptRobotStateMessage_Exception e) {
// the message received form ur was corrupted , ignore and wait for next message
run = true;
}
}
}
command.robotStateMessage = message;
}
The problem occurs when I stop reading from the BufferedInputStream ur_in for a while. Any pause longer than aproximatly a minute and the ur_in.read(data) blocks after consuming all the buffered old data.
After consuming buffered data there seems to be no new data on the BufferedInputStream. Using a second tool to listen to the data from the robot, I can clearly see that the status messages are still broadcasted.
The Socket is still alive but the Inputstream seems to have "died". I put a timeout on the socket so that the read() does not block forever, but that does not solve my problem, that I receive no more data over the BufferdInputStream.
The only thing that helped was reconnecting the socket, which is not a satisfying solution for my problem.
Any help or suggestions how to solve this are appreciated. If you need more information please ask.
I assume that you are using TCP. If you don't read from the buffer the the robot will be notified by your socket to stop transmission until the buffer has capacity to receive more data. The robot software will evetually have to handle that no data can be written and probably disconnects your client. You should not use the socket buffer to store data and instead as quickly as possible move the data to an other buffer. Setting a larger receive buffer will probably help a little, but is not a good idea.
The legacy J2EE application details :
JSP + Servlets(2.4)
Websphere Application Server 7.0
The view is using IE frames, core javascript and so on
The user's action :
User's search returning > 900 rows takes some time to display (NO pagination)
User then clicks on 'Download' button which again triggers a form submit.
Following is the code snippet that is executed in the action servlet :
public class DownloadFileEvent extends ActionGeneric {
java.text.SimpleDateFormat df_file = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss");
public void run(HttpServletRequest request, HttpServletResponse response) throws Exception {
String errormsg = null;
StringBuffer LineBuffer = null;
// read parameters.
String _v = request.getParameter("view");
// Start traitment.
try {
// get sessions.
ServletOutputStream out = response.getOutputStream();
// Create title columns.
response.setContentType("application/csv");
response.setHeader("Content-Disposition", "inline; filename = " + getFilename(_v));
LineBuffer = new StringBuffer();
//Get the string response from some business method
//String v_wrk = getOutflow(request, _v).toString();
LineBuffer.append(v_wrk);
LineBuffer.append("\r\n");
out.print(LineBuffer.toString());
out.flush();
// end.
}// fin try
catch (Exception e) {
errormsg = e.getMessage();
} finally {
// to do.
}
}// end run.
}// fin class
The issue :
Since the 'Download' takes some time, the user moves to other screen
When he comes back, the 'Open/Save/Save As' prompt is there already for some time. Now when user saves/opens the file but instead of 900 rows, there are less than 100 rows
Surprisingly, if the open/save is done immediately, all the rows are downloaded
In the catch block, I had put a log but there is no exception anywhere
The issue is not simulated on my local machine(Windows, WAS 7) or in the SYSTEM test environment(Linux, WAS 8.5) but surfaces on ACCEPTANCE (WAS 7, Linux) and PRODUCTION(WAS 7, Linux). The ACCEPTANCE and PRODUCTION have load balancers, web server set up but NOT in systest or local
How shall I proceed ?
Try a high SendBufferSize in your web servers. If the client does not read while the dialog is up, this will prevent the webserver from seeing writes eventually block then timeout.
I'm working on a server/client project in Java where, at any point during the running of the program, the client can request a set of details related to a unique ID, and the server returns the relevant set of details. This is done through PrintWriter objects accessing the socket.getOutputStream, and works fine.
I am trying to also include the sending/receiving of an image from the server to the client, and have met some very strange behaviour from the program.
The methods that send and receive the images are shown below:
SERVER-SIDE:
//send image associated with item
//through ObjectOutputStream to client
private void sendItemImage(BidItem item)
{
try
{
//wrap object output stream around
//output stream to client at this socket
ObjectOutputStream imageOutput =
new ObjectOutputStream(client.getOutputStream());
//send image object to client
imageOutput.writeObject(item.getItemImage());
}
catch (IOException ioEx)
{
//alert server console
System.out.println("\nUnable to send image for item "
+ item.getItemCode() + " to "
+ bidderName + "!");
//no exit from system
//bidding can still continue
}
}
CLIENT-SIDE:
//to be displayed on GUI
private static void receiveItemImage()
{
try
{
//wrap ObjectInputStream around socket
//to receive objects sent from server
ObjectInputStream imageInput =
new ObjectInputStream(socket.getInputStream());
//read in image and store in ImageIcon instance
image = (ImageIcon) imageInput.readObject();
//re-create label object to be blank
imageLabel = new JLabel();
//remove label containing last image
imagePanel.remove(imageLabel);
//just ignores command if it does not already contain image
//apply image to label
imageLabel.setIcon(image);
//apply image to CENTER of panel
imagePanel.add(imageLabel, BorderLayout.CENTER);
}
//problem in input stream
catch (IOException ioEx)
{
//alert user
JOptionPane.showMessageDialog(
null, "Error receiving image!");
//allow system to continue
//no exit
}
//problem casting to ImageIcon type
catch (ClassNotFoundException cnfEx)
{
//alert user
JOptionPane.showMessageDialog(
null, "Error converting Object to ImageIcon!");
//allow system to continue
//no exit
}
}
So, each time there is a request, an ObjectOutpuStream and ObjectInputStream are created to handle the passing of the image, using the socket.getOutputStream/socket.getInputStream.
These methods are first called when a client connects to the server, and the first image and set of details are sent automatically. This works fine, but any subsequent attempts at requesting the image throughout the program result in the catch (IOException) clause being met, and the error messages shown above being displayed.
I cannot for the life of me work out why it would work the first time but not again after this. If anyone could point me in the right direction, that would be great!
Thanks,
Mark
You should only wrap a stream once. In this case, you can't wrap it again as this will not work for an Object Stream.
Once you are wrapping the stream only once, call ObjectOutputStream.reset() after sending an image. If you don't do this it will just pass the reference to the object again (and use a lot of memory)
Here is my code for downloading a file I am passing a URL, but I want to make my download manager catch the link automatically
private void button1_Click_1(object sender, EventArgs e)
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
string []filename;
string fn ; fn=textBox1.Text;
int i;
filename =fn.Split('/');
for (i = 1; i <= filename.Length; i++) ;
string oname=filename[i-2];
//////// Starts the download
client.DownloadFileAsync(new Uri("http://dinirah.wen.ru/Internet-k-zariye-musalmano-gumrah-kia-ja-raha.mp3"), textBox2.Text+"\\"+oname);
//////// the above i passed the url to download.
label4.Text = i.ToString();
button1.Text = "Download In Process";
button1.Enabled = false;
}
Now I want to make my downloader automatically get the download url, and store it in a string which it then passes as an URL later.
You should develop browser extension(s) and then you would be able to intercept the file download process.
The other way is to monitor your computer's network connections and intercept when a desired file type is being requested. I have found that IDM intercepts my downloads even if I am downloading it using my programs (If enabled in IDM to intercept any download). Be careful with windows update files, diagnostic files and any other unknown file.