Im trying to develop a simple java code which will upload some contents from local machine to a server/another machine.I used the below code
import sun.net.ftp.*;
import java.io.*;
public class SftpUpload {
public static void main(String args[]) {
String hostname = "some.remote.machine"; //Remote FTP server: Change this
String username = "user"; //Remote user name: Change this
String password = "start123"; //Remote user password: Change this
String upfile = args[0]; //File to upload passed on command line
String remdir = "/home/user"; //Remote directory for file upload
FtpClient ftp = new FtpClient();
try {
ftp.openServer(hostname); //Connect to FTP server
ftp.login(username, password); //Login
ftp.binary(); //Set to binary mode transfer
ftp.cd(remdir); //Change to remote directory
File file = new File(upfile);
OutputStream out = ftp.put(file.getName()); //Start upload
InputStream in = new FileInputStream(file);
byte c[] = new byte[4096];
int read = 0;
while ((read = in.read(c)) != -1 ) {
out.write(c, 0, read);
} //Upload finished
in.close();
out.close();
ftp.closeServer(); //Close connection
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
But it is showing error in Line 11 as 'Cannot instantiate the type FtpClient'.
Can some one help me how to rectify it.
You cannot instantiate it because sun.net.ftp.FtpClient is abstract class.
I suggest using Apache Commons Net instead of playing with sun.x packages. FTP client example can be found from here.
If you do want to use the Sun classes, use FtpClient.create(), as per the JavaDoc for this class.
i have resolved the exception.thats because my machine is connected in a network which doesnt allow FTP connection.when i tried it in a private dongle it worked.
Related
I was doing an assignment to create a UI based client to send and display files. The server will both send and receive the files (just like file upload and download to ftp).
Now I have only two problems:
if we send a file to server for storing the file on disk from client it writes data to file and then stores file with name as null .(I know that this is because I am not sending file name to server with which to store the file). I want to send the server both name of file and contents of the file. how should I do it?
Another thing that the client and server both have File Send and File Receive methods which run in Thread. when The client requests file the File Send of server should send it and when the client uploads file the File receive of server should accept it, but if I just start both the threads in MainMethod one of them says that the connection is refused.(As the File receive means that the File send of client should run before file receive of server and vice versa) how should I do it?
Main Method of CLIENT
public class MainMethod {
public static void main (String[] args) throws Exception {
new FileScreen();
new FileReceive().start();
new FileSend().start();
}
}
Main Method of SERVER
public class MainMethod {
public static void main (String[] args) throws IOException {
new FileSend().start();
new FileReceive().start();
}
}
Finally FileSend of Client
public void run () {
socket = serverSocket.accept ();
dis = new DataInputStream (socket.getInputStream ());
dos = new DataOutputStream (socket.getOutputStream ());
dos.writeUTF(Filename); //tried to send filename to server
:does not work
bufferedReader = new BufferedReader(new FileReader(path));
while ( (data1 = bufferedReader.readLine ()) != null ){
if ( flag == 0 ){
fileData = data1;
flag = 1;
}else {
fileData = fileData+"\n"+data1;
}
}
bufferedReader.close ();
dos.writeUTF (fileData); //send file contents to server
}
File Receive of SERVER
public void run () {
downloadFileName = dis.readUTF(); //this line should read name :- not working
downloadFileContent = dis.readUTF (); // this line works fine in absence of above line
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("/home/user/Client&Server/ServerReceive/"+downloadFileName));
bufferedWriter.write (downloadFileContent);
bufferedWriter.close ();
}
im trying to send files to FTPS server
connection method: FTPS, ACTIVE, EXPLICIT
setFileType(FTP.BINARY_FILE_TYPE);
setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
Checking the reply string right after connect i got:
234 AUTH command ok. Expecting TLS Negotiation.
from here
234 Specifies that the server accepts the authentication mechanism specified by the client, and the exchange of security data is complete. A higher level nonstandard code created by Microsoft.
while trying to send file with storeFile or storeUniqeFile i get false
checking the reply string right after store file i got: 501 Server cannot accept argument.
what is weird i was able creating a directory to this client without any issues
with makeDirectory("test1");
i was trying both this links : link1 , link2
FOR EXAMPLE when i was trying to use ftp.enterLocalPassiveMode(); before ftp.storeFile(destinationfile, in);
i got time out error .
Does anyone have any idea how to solve it ?
public static void main(String[] args) throws Exception {
FTPSProvider ftps = new FTPSProvider();
String json = "connection details";
DeliveryDetailsFTPS details = gson.fromJson(json, DeliveryDetailsFTPS .class);
File file = File.createTempFile("test", ".txt");
FileUtils.write(file, " some test", true);
try (FileInputStream stream = new FileInputStream(file)) {
ftps.sendInternal(ftps.getClient(details), details, stream, file.getName());
}
}
protected void sendInternal(FTPClient client, DeliveryDetailsFTPS details, InputStream stream, String filename) throws Exception {
try {
// release the enc
DeliveryDetailsFTPS ftpDetails = (DeliveryDetailsFTPS) details;
setClient(client, ftpDetails);
boolean isSaved = false;
try (BufferedInputStream bis = new BufferedInputStream(stream)) {
isSaved = client.storeFile(filename, bis);
}
client.makeDirectory("test1");
client.logout();
if (!isSaved) {
throw new IOException("Unable to upload file to FTP");
}
} catch (Exception ex) {
LOG.debug("Unable to send to FTP", ex);
throw ex;
} finally {
client.disconnect();
}
}
#Override
protected FTPClient getClient(DeliveryDetails details) {
return new FTPSClient(isImplicitSSL((DeliveryDetailsFTPS ) details));
}
protected void setClient(FTPClient client, DeliveryDetailsFTPS details) throws Exception {
DeliveryDetailsFTPS ftpDetails = (DeliveryDetailsFTPS ) details;
client.setConnectTimeout(100000);
client.setDefaultTimeout(10000 * 60 * 2);
client.setControlKeepAliveReplyTimeout(300);
client.setControlKeepAliveTimeout(300);
client.setDataTimeout(15000);
client.connect(ftpDetails.host, ftpDetails.port);
client.setBufferSize(1024 * 1024);
client.login(ftpDetails.username, ftpDetails.getSensitiveData());
client.setControlEncoding("UTF-8");
int code = client.getReplyCode();
if (code == 530) {
throw new IOException(client.getReplyString());
}
// Set binary file transfer
client.setFileType(FTP.BINARY_FILE_TYPE);
client.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
if (ftpDetails.ftpMode == FtpMode.PASSIVE) {
client.enterLocalPassiveMode();
}
client.changeWorkingDirectory(ftpDetails.path);
}
I have tried this solution as well didn't solve the problem:
they only way i was able send file is with FileZilla and it is using FTPES .
But i need my Java code to do it . can anyone give me a clue
I have tried almost any possible solution offered on different websites could not make it work with Apache FTPS CLIENT ,
had to use a different class which worked like a charm here is a snippet:
com.jscape.inet.ftps Link
private Ftps sendWithFtpsJSCAPE(ConnDetails details, InputStream stream, String filename) throws FtpException, IOException {
Ftps ftp;
FtpConnectionDetails ftpDetails = FtpConnectionDetails details;
ftp = new Ftps(ftpDetails.getHost(), ftpDetails.getUsername(), ftpDetails.getPassword());
if (ftpDetails.getSecurityMode().equals(FtpConnectionDetails.SecurityMode.EXPLICIT)) {
ftp.setConnectionType(Ftps.AUTH_TLS);
} else {
ftp.setConnectionType(Ftps.IMPLICIT_SSL);
}
ftp.setPort(ftpDetails.getPort());
if (!ftpDetails.getFtpMode().equals(FtpMode.ACTIVE)) {
ftp.setPassive(true);
}
ftp.setTimeout(FTPS_JSCAPE_TIME_OUT);
ftp.connect();
ftp.setBinary();
ftp.setDir(ftpDetails.getPath());
ftp.upload(stream, filename);
return ftp;
}
I'm struggling with getting file upload/download to work properly in Play framework 2.2.2. I have a Student class with a field called "cv". It's annotated with #Lob, like this:
#Lob
public byte[] cv;
Here are the upload and download methods:
public static Result upload() {
MultipartFormData body = request().body().asMultipartFormData();
FilePart cv = body.getFile("cv");
if (cv != null) {
filenameCV = cv.getFilename();
String contentType = cv.getContentType();
File file = cv.getFile();
Http.Session session = Http.Context.current().session();
String studentNr = session.get("user");
Student student = Student.find.where().eq("studentNumber", studentNr).findUnique();
InputStream is;
try {
is = new FileInputStream(file);
student.cv = IOUtils.toByteArray(is);
} catch (IOException e) {
Logger.debug("Error converting file");
}
student.save();
flash("ok", "Vellykket! Filen " + filenameCV + " ble lastet opp til din profil");
return redirect(routes.Profile.profile());
} else {
flash("error", "Mangler fil");
return redirect(routes.Profile.profile());
}
}
public static Result download() {
Http.Session session = Http.Context.current().session();
Student student = Student.find.where().eq("studentNumber", session.get("user")).findUnique();
File f = new File("/tmp/" +filenameCV);
FileOutputStream fos;
try {
fos = new FileOutputStream(f);
fos.write(student.cv);
fos.flush();
fos.close();
} catch(IOException e) {
}
return ok(f);
}
The file seems to be correctly saved to the database (the cv field is populated with data, but it's obviously cryptic to me so I don't know for sure that the content is what it's supposed to be)
When I go to my website and click the "Download CV" link (which runs the download action), the file gets downloaded but can't be opened - saying the PDF viewer can't recognize the file etc. (Files uploaded have to be PDF)
Any ideas on what might be wrong?
Don't keep your files in DB, filesystem is much better for that! Save uploaded file on the disk with some unique name, then in your database keep only path to the file as a String!
It's cheaper in longer run (as said many times)
It's easier to handle downloads, i.e. in Play all you need to serve PDF is:
public static Result download() {
File file = new File("/full/path/to/your.pdf");
return ok(file);
}
it will set proper headers, like Content-Disposition, Content-Length and Content-Type not only for PDFs
I managed to create a method which uploads a file into a directory.
How would I have to change this so I could copy a file from /123.html to /en/123.html via JSch?
public void upFile(String source, String fileName, String destination) throws Exception {
try {
try {
// 改变当前路径
client.cd(destination);
} catch (Exception e) {
System.out.println("当前目录不存在,新建目录!");
JschCreateDir.createDir(host, port, username, password, destination);
client.cd(destination);
}
// 上传本地文件 到当前目录
File file = new File(source + fileName);
client.put(new FileInputStream(file), fileName);
} catch (Exception e) {
logout();
throw e;
}
}
I understand your question that you want to copy a file on the server from one directory to another one (and not a local file to the server, which your code already seems to do).
Unfortunately, the SFTP protocol (which is implemented by JSch's ChannelSFTP class) doesn't support copying directly on the server.
You certainly can combine the put and get to copy the file from one location to another, but this will send the contents twice through the wire from server to client and back.
A better way would be to use an exec channel, and simply directly issue the server's system's copy command. On a unixoid server, this would be cp /123.html /en/123.html. (This assumes you have shell access to the server, not an sftp-only access, as I already did see somewhere.)
Here is some code (not tested, you might need to add exception handling):
public void copyFile(Session session, String sourceFile, String destinationFile) {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("cp " + sourceFile + " " + destinationFile);
channel.connect();
while(channel.isConnected()) {
Thread.sleep(20);
}
int status = channel.getExitStatus();
if(status != 0)
throw new CopyException("copy failed, exit status is " + status);
}
i want to copy a file from a server to a client in java.this is my code up to now
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
public class Copy {
private ListDirectory dir = new ListDirectory();
public Copy() {
}
public String getCopyPath(String file) throws Exception {
String path = dir.getCurrentPath();
path += "\\" + file;
return path;
}
public void copyFile(String file) {
try {
File inputFile = new File(dir.getCurrentPath());
URL copyurl;
InputStream outputFile;
copyurl = new URL(getCopyPath(file));
outputFile = copyurl.openStream();
FileOutputStream out = new FileOutputStream(inputFile);
int c;
while ((c = outputFile.read()) != -1)
out.write(c);
outputFile.close();
out.close();
} catch (Exception e) {
System.out.println("Failed to Copy File from server");
e.printStackTrace();
}
}
public static void main(String args[]) {
String a = "put martin";
String b = a.substring(0, 3);
String c = a.substring(4);
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
Problem is , the server is not uploadded online , but it is on my local drive, and the URL thing doesnt work. is there any other way? is this way correct? thanks
If you're expecting to access your file from the local file system (whether that be via network drive or a local disk), you'll need to treat this as if it is a straight file copy.
If you're expecting to access your file as if it is available for download from an HTTP server, you will need to treat it as an HTTP download (which is what it looks like you're trying to do with the URL).
If you want to test the HTTP download functionality using a file on your local system, just set up a simple HTTP server on your dev machine with a directory on your local system, and give your HTTP-downloading code a URL pointing to that local server (on http://localhost, or using your IP address).
Unfortunately, HTTP is a very different animal from a file system, and I don't think there's any way to use the same code to handle both scenarios. If you want your program to ultimately support both protocols, you should build methods/classes to handle both situations, and then have your program detect and use the appropriate protocol for a given path. You'll need to do the same for any other protocol you wish to support (FTP, SFTP, etc).