I wrote this class (from examples) to download the header of all the files contained in a remote FTP folder. It works well, but when it approaches to download the file #146 it stops with a NullPointException. The file #146 exists and I can download it as a single file actually.
In the method remotePathLong contains all the remote folders written in a single line and spaced with the space character.
public void downloadHeader(String remotePathLong, String destPath, int bytes) {
String remotePath;
FTPFile[] fileList;
String[] fileNameList;
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int indice = 0;
int iP = 1;
File downloadFile;
String destFile;
String remoteFile;
byte[] bytesArray;
int bytesRead = -1;
while ((remotePath = getPath(remotePathLong, iP)) != null) {
System.out.println("Loading file list from the server.....");
fileNameList = ftpClient.listNames(remotePath);
for (String file : fileNameList) {
indice += 1;
System.out.println(indice + " - Downloading: " + file);
//Select files
destFile = destPath.concat(file);
downloadFile = new File(destFile);
outputStream = new BufferedOutputStream(new FileOutputStream(downloadFile));
//Download remote file (from ftp)
remoteFile = remotePath.concat(file);
inputStream = ftpClient.retrieveFileStream(remoteFile);
bytesArray = new byte[bytes];
bytesRead = inputStream.read(bytesArray);
outputStream.write(bytesArray);
//Save into file
outputStream.close();
inputStream.close();
iP += 1;
}
}
} catch (IOException ex) {
} final{
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
}
catch (IOException ex1) {
System.out.println("Error: " + ex1.getMessage());
}
}
when it reaches bytesRead = inputStream.read(bytesArray), at the iteration #146 it gives the error. But if at the same iteration i reinitialize the connection it works.
Does anybody have a suggestion please?
It is possible your connection times out due to a network traffic or a file size that happens to be 146th.
Can you print the 146th file name and check its size. Also you can increase the FTP connection timeout period
ftpClient.setControlKeepAliveTimeout(300); // set timeout to 5 minutes
Related
How we can push multiple files from our local folder to smb share folder using java. I can do with my single file using smbFile and it is working. I am looking for pushing multiple file push to smb share.
Any reference links and sample code would be helpful.
Thanks.
EDIT, Reference of code :
SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern);
if (files == null)
return false;
output(sb, logger, " Source file count: " + files.length);
String destFilename;
FileOutputStream fileOutputStream;
InputStream fileInputStream;
byte[] buf;
int len;
for (SmbFile smbFile: files) {
destFilename = destinationPath + smbFile.getName();
output(sb, logger, " copying " + smbFile.getName());
try {
fileOutputStream = new FileOutputStream(destFilename);
fileInputStream = smbFile.getInputStream();
buf = new byte[16 * 1024 * 1024];
while ((len = fileInputStream.read(buf)) > 0) {
fileOutputStream.write(buf, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
} catch (SmbException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e);
e.printStackTrace();
return false;
}
This works fine if i try to send one single file of anyformat. But if would like to send multiple file to smb share fromocal folder. For This i need thr help please. Thanks.
Try to declare a SmbFile object that is a root folder of your folder, that you want to upload to the shared folder. Then iterate through the root.listFiles() array.
Put the uploadable files in that folder.
I assume that, your SmbFile[] files array only contains one file if it's only uploading one file.
Or another possible solution is that, try to use SmbFileOutputStream and SmbFileInputStream instead of FileOutputStream and FileInputStream.
I'm guessing you are using jcifs-library (which is quite outdated), so firstly I would recommend you to switch library. I switched to SMBJ and here is how I'm uploading file:
private static void upload(File source, DiskShare diskShare, String destPath, boolean overwrite) throws IOException {
try (InputStream is = new java.io.FileInputStream(source)) {
if (destPath != null && is != null) {
// https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files
Set<AccessMask> accessMask = new HashSet<>(EnumSet.of(
AccessMask.FILE_READ_DATA,
AccessMask.FILE_WRITE_DATA, AccessMask.DELETE));
Set<SMB2ShareAccess> shareAccesses = new HashSet<>(
EnumSet.of(SMB2ShareAccess.FILE_SHARE_WRITE));
Set<FileAttributes> createOptions = new HashSet<>(
EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL));
try (com.hierynomus.smbj.share.File file = diskShare
.openFile(destPath, accessMask, createOptions,
shareAccesses,
(overwrite
? SMB2CreateDisposition.FILE_OVERWRITE_IF
: SMB2CreateDisposition.FILE_CREATE),
EnumSet.noneOf(SMB2CreateOptions.class))) {
int bufferSize = 2048;
if (source.length() > 20971520l) {
bufferSize = 131072;
}
byte[] buffer = new byte[bufferSize];
long fileOffset = 0;
int length = 0;
while ((length = is.read(buffer)) > 0) {
fileOffset = diskShare.getFileInformation(destPath)
.getStandardInformation().getEndOfFile();
file.write(buffer, fileOffset, 0, length);
}
file.flush();
file.close();
} finally {
is.close();
}
}
}
}
Of course takes a little effort on connecting the SMB-server and authenticating before this, but that's another case...
I'm trying to upload some files to a Local FTP server. The observable list has all the files, and are uploaded by looping the array
I'm using the commons-net-3.6.jar Library.
The Directory and everything get's created but the images uploaded are corrupted. Huge change in color (looks like an old static TV image with colors)
What am i doing wrong?
NOTE! Something I noticed was that the sizes of file's are the same in KB but differs slightly by bytes.
ObservableList<File> uploadFiles = FXCollections.observableArrayList();
FTPClient client = new FTPClient();
InputStream fis = null;
FTPConnection con = new FTPConnection();
con.readData(); //gets username and password
uploadFiles = Something.getFiles(); //Gets Files
try {
client.connect(con.getServerIp());
client.login(con.getUsername(), con.getPassword());
String pathname = getPathname();
client.makeDirectory(pathname);
for (int i = 0; i < uploadFiles.size(); i++) {
fis = new FileInputStream(uploadFiles.get(i));
String filename = uploadFiles.get(i).getName();
String uploadpath = pathname+"/"+filename;
System.out.println("Uploading File : " + uploadpath);
client.storeFile(uploadpath, fis);
}
client.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
Setting the file type to Binary did the Trick!
client.setFileType(FTP.BINARY_FILE_TYPE);
I'm writing a program to download a PDF file from server. I'm using some program given here Download file by passing URL using java code, this solution works fine for the sample URL provided in the first answer, but not for PDF, I'm replacing just the URL. Below is my code.
import java.io.*;
import java.net.*;
public class FileDownloadTest {
final static int size = 1024;
public static void fileUrl(String fAddress, String localFileName, String destinationDir) {
// localFileName = "Hello World";
OutputStream outStream = null;
URLConnection uCon = null;
InputStream is = null;
try {
URL url;
byte[] buf;
int byteRead, byteWritten = 0;
url = new URL(fAddress);
outStream = new BufferedOutputStream(new FileOutputStream(destinationDir + "\\" + localFileName));
uCon = url.openConnection();
is = uCon.getInputStream();
buf = new byte[size];
while ((byteRead = is.read(buf)) != -1) {
outStream.write(buf, 0, byteRead);
byteWritten += byteRead;
}
System.out.println("Downloaded Successfully.");
System.out.println("File name:\"" + localFileName + "\"\nNo ofbytes :" + byteWritten);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void fileDownload(String fAddress, String destinationDir) {
int slashIndex = fAddress.lastIndexOf('/');
int periodIndex = fAddress.lastIndexOf('.');
String fileName = fAddress.substring(slashIndex + 1);
if (periodIndex >= 1 && slashIndex >= 0 && slashIndex < fAddress.length() - 1) {
fileUrl(fAddress, fileName, destinationDir);
} else {
System.err.println("path or file name.");
}
}
public static void main(String[] args) {
String fAddress = "http://singztechmusings.files.wordpress.com/2011/09/maven_eclipse_and_osgi_working_together.pdf";
String destinationDir = "D:\\FileDownload";
fileDownload(fAddress, destinationDir);
}
}
Here, This pdf has 73 pages, and in my folder, it is download as a PDF of 1KB, when opened in Acrobat Reader, it says that the file might be corrupted.
I've also tried the code provided here https://dzone.com/articles/java-how-save-download-file, but the result is same.
please let me know how can I fix this.
Thanks
If you check the downloaded file content, you can see it is html. The server is redirecting the original request to https url. Use url https://singztechmusings.files.wordpress.com/2011/09/maven_eclipse_and_osgi_working_together.pdf instead.
Or use http client with automatic redirect handling, ala http-commons
You define a Variable size = 1024 and use this to define your Buffer.
So logically you can only write 1 KB into it.
But if the input Stream reads more at once it will be lost ... So change your Buffer size to a value which would be able to contain most documents or try to determine the necessary size
i am trying to transfer files via socket. I've used only a single socket for communication( not according to FTP protocol i guess). The following code will transfer the first file successfully but is not able to tra nsfer second file as the filename doesn't change but the server gets the read bytes of the new data file. I think the problem is of the readUTF and writeUTF.
Here is my server side code. Remember this accepts the file.Not send file.
public int listenPort() throws IOException{
System.out.println("LISTENING");
try{
//this.dis = new DataInputStream(this.socketClient.getInputStream());
if( this.dis.available() != 0 ){
String filename = this.dis.readUTF();
this.fos = new FileOutputStream("/home/ankit07/" + filename);
int bytesRead = (int) IOUtils.copyLarge(this.dis,this.fos); //no of bytes copied
return bytesRead;
}else{
return 0;
}
}finally{
}
}
Here is my client side. Remember this side sends the file. Not accept
public void getFile(String filename) throws IOException{
try{
this.file = this.window.file;
DataOutputStream dos = new DataOutputStream(this.socketClient.getOutputStream());
dos.writeUTF(filename);
FileInputStream fis = new FileInputStream(this.file);
int readByte = (int) IOUtils.copyLarge(fis, dos);
System.out.println("FILE SENT : " + filename + " Bytes :" + readByte);
//this.socketClient.close();
}finally{
//if( this.os!=null) this.os.close();
if( this.window.file != null) this.window.file = null;
if( this.file != null) this.file = null;
//if( this.socketClient!=null) this.socketClient.close();
}
}
The file selections are done in other class window.
The method to select the file is in the window class. This has a public File property to hold the file and then i've called the getFile(String filename) to send the file name and to refer to the selected file, the client has File property to refer to the same file.
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Object src = e.getSource();
if( src instanceof JButton ){ //Browse clicked
JFileChooser fc = new JFileChooser();
int returnVal = fc.showDialog(null, "SELECT FILE");
if( returnVal == JFileChooser.APPROVE_OPTION){
this.file = fc.getSelectedFile();
try {
this.sc.getFile(this.file.getName());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}else{
//unable to select file
}
}
}
Also i am not able to transfer large files like mp3 and video besides my initial problem. It would be helpful if you'd know any solutions.
Thanks you !!!!
You're sending filename, but then you're sending this.file. There's nothing here to show that they're always referring to the same file. Indeed you have a RS file, in this.window.file. You need to sort out all this confusion.
I've made a basic client server FTP program using sockets, but for some reason files are getting corrupted during the transfer. In the case below, I'm pushing a file to the server from the client. It almost works, since some files (such as a .png) transfer and open fine, but others (a .docx) don't. Any file that I transfer has a different MD5 to the one I sent.
Client code:
File file = null;
FTPDataBlock transferBlock;
int numBytesRead = 0;
int blockNumber = 1;
int blockSize = 1024;
byte[] block = new byte[blockSize];
fc = new JFileChooser();
// select file to upload
int returnVal = fc.showOpenDialog(Client.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
try {
// get total number of blocks and send to server
int totalNumBlocks = (int)Math.ceil((file.length()*1.0) / blockSize);
System.out.println("File length is: " + file.length());
FTPCommand c = new FTPCommand("PUSH", Integer.toString(totalNumBlocks));
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(c);
oos.flush();
// send to server block by block
FileInputStream fin = new FileInputStream(file);
while ((numBytesRead = fin.read(block)) != -1){
transferBlock = new FTPDataBlock(file.getName(), blockNumber, block);
blockNumber++;
System.out.println("Sending block " + transferBlock.getBlockNumber() + " of " + totalNumBlocks);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(transferBlock);
oos.flush();
}
fin.close();
System.out.println("PUSH Complete");
// get response from server
ois = new ObjectInputStream(sock.getInputStream());
FTPResponse response = (FTPResponse)ois.readObject();
statusArea.setText(response.getResponse());
} catch (IOException | ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Server Code:
else if (cmd.getCommand().equals("PUSH")){
// get total number of file blocks
int totalNumBlocks = Integer.parseInt(cmd.getParameters());
// get first block
in = new ObjectInputStream(sock.getInputStream());
FTPDataBlock currentBlock = (FTPDataBlock)in.readObject();
// create file and write first block to file
File file = new File (workingDirectory + File.separator + currentBlock.getFilename());
FileOutputStream fOut = new FileOutputStream(file);
fOut.write(currentBlock.getData());
fOut.flush();
// get remaining blocks
while(currentBlock.getBlockNumber()+1 <= totalNumBlocks){
in = new ObjectInputStream(sock.getInputStream());
currentBlock = (FTPDataBlock)in.readObject();
fOut.write(currentBlock.getData());
fOut.flush();
}
fOut.close();
// send response
FTPResponse response = new FTPResponse("File Received OK");
out = new ObjectOutputStream(sock.getOutputStream());
out.writeObject(response);
}
FTPDataBlock class:
public class FTPDataBlock implements Serializable{
private static final long serialVersionUID = 1L;
private String filename;
private int blockNumber; // current block number
private byte[] data;
//constructors & accessors
}
I'm sure it's something small that I'm missing here. Any ideas?
This happened because the server was writing whole 1024 byte blocks to the file, even if there was less than 1024 bytes actually written to the block.
The solution (thanks to #kdgregory) was to use the return value of FileInputStream.read() to populate a new attribute in my FTPDataBlock class, int bytesWritten.
Then on the server side I could use:
FileOutputStream.write(currentBlock.getData(), 0, currentBlock.getBytesWritten());
to write the exact number of bytes to the file, instead of the whole block every time.
I think there may be a problem with the file extension. provide a option in the client side as:
FILE_TO_RECEIVED = JOptionPane.showInputDialog("Please enter the Drive followed by the file name to be saved. Eg: D:/xyz.jpg");
it is to help you to provide the correct file extension name.
then i think u should also provide the file size in client side like:
public final static int FILE_SIZE = 6022386;
and in then in the array block u used u can make the following changes as:
try {
sock = new Socket(SERVER, SOCKET_PORT);
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
}