I'm trying to create a Java application which can copy files from a Unix Samba share to a Windows folder. In order to achieve that, I'm using the JCIFS library.
I have the following code:
SmbFile smbFromFile = new SmbFile("smb:////192.168.10.1//data", auth);
smbFromFile.copyTo(destinationFolder);
I'm modifying it to:
SmbFile smbFromFile = new SmbFile("smb:////192.168.10.1//data", auth);
SmbFile destinationFolder = new SmbFile("C:\\Temp\\IN\\");
smbFromFile.copyTo(destinationFolder);
But it gives me the following error:
Exception in thread "main" jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:546)
at jcifs.smb.SmbTransport.send(SmbTransport.java:663)
at jcifs.smb.SmbSession.sessionSetup(SmbSession.java:390)
at jcifs.smb.SmbSession.send(SmbSession.java:218)
at jcifs.smb.SmbTree.treeConnect(SmbTree.java:176)
at jcifs.smb.SmbFile.doConnect(SmbFile.java:911)
at jcifs.smb.SmbFile.connect(SmbFile.java:957)
at jcifs.smb.SmbFile.connect0(SmbFile.java:880)
at jcifs.smb.SmbFile.copyTo(SmbFile.java:2303)
at RU.Tasks.Task3_Load_MedioSCP_Tekelek_file_To_DB_Oracle_BMCDB.main(Task3.java:203)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
If I try to create a new file on the Samba share, it works as expected:
String user = "usersamba";
String pass ="1234";
String hostname = "192.168.10.1";
String sharedFolder = "data/new";
String path = "smb://"+hostname+"/"+sharedFolder+"/test.txt";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",user, pass);
SmbFile smbFile = new SmbFile(path,auth);
SmbFileOutputStream smbfos = new SmbFileOutputStream(smbFile);
smbfos.write("testing....and writing to a file".getBytes());
System.out.println("completed ...nice !");
Please help to resolve this problem.
option resolve to the problem
InputStream in = null;
OutputStream out = null;
try{
String SambaURL= "smb://usersamba:1234#192.168.1.110/data/1b.csv";
File destinationFolder = new File("C:\\Temp\\IN\\");
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS_");
File child = new File (destinationFolder+ "/" + fmt.format(new Date()) +"1b.csv");
SmbFile dir = new SmbFile(SambaURL);
SmbFile fileToGet=new SmbFile(SambaURL);
fileToGet.connect();
in = new BufferedInputStream(new SmbFileInputStream(fileToGet));
out = new BufferedOutputStream(new FileOutputStream(child));
byte[] buffer = new byte[4096];
int len = 0; //Read length
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
out.flush(); //The refresh buffer output stream
}
catch (Exception e) {
String msg = "The error occurred: " + e.getLocalizedMessage();
System.out.println(msg);
}
finally {
try {
if(out != null) {
out.close();
}
if(in != null) {
in.close();
}
}
catch (Exception e) {}
}
source here
You need the proper auth mechanisms. See for example:
private static void GetFiles() throws IOException {
jcifs.Config.registerSmbURLHandler();
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(
prop.getProperty("smbDomain"), prop.getProperty("smbUser"),
prop.getProperty("smbPass"));
StaticUserAuthenticator authS = new StaticUserAuthenticator(
prop.getProperty("smbDomain"), prop.getProperty("smbUser"),
prop.getProperty("smbPass"));
FileSystemOptions opts = new FileSystemOptions();
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts,
authS);
SmbFile smbFile = new SmbFile(prop.getProperty("smbURL"),auth);
FileSystemManager fs = VFS.getManager();
String[] files = smbFile.list();
for(String file:files) {
SmbFile remFile = new SmbFile(prop.getProperty("smbURL") + file, auth);
SmbFileInputStream smbfos = new SmbFileInputStream(remFile);
OutputStream out = new FileOutputStream(file);
byte[] b = new byte[8192];
int n;
while ((n = smbfos.read(b)) > 0) {
out.write(b, 0, n);
}
smbfos.close();
out.close();
}
}
Related
I am trying to make a java program download an app from my server by getting download link from it with this code :
private void downloadFile(String link) throws Exception {
URL url = new URL(link);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
int max = conn.getContentLength();
pane.setText(pane.getText()+"\n"+"Downloding files...\nUpdate Size : "+(max/1000000)+" Mb");
BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(new
File("update.zip")));
byte[] buffer = new byte[32 * 1024];
int bytesRead = 0;
int in = 0;
while ((bytesRead = is.read(buffer)) != -1) {
in += bytesRead;
fOut.write(buffer, 0, bytesRead);
}
fOut.flush();
fOut.close();
is.close();
pane.setText(pane.getText()+"\nDownload Completed Successfully!");
and it is working fine ... I did search about how to bind my progress bar to this download link but I couldnt figure it out .... I would appreciate any kind of help.
Create a Task and perform your download in that Task’s call method:
String link = /* ... */;
File downloadsDir = new File(System.getProperty("user.home"), "Downloads");
downloadsDir.mkdir();
File file = File(downloadsDir, "update.zip");
Task<Void> downloader = new Task<Void>() {
#Override
public Void call()
throws IOException {
URL url = new URL(link);
URLConnection conn = url.openConnection();
long max = conn.getContentLengthLong();
updateMessage(
"Downloading files...\nUpdate Size : " + (max/1000000) + " MB");
try (InputStream is = conn.getInputStream();
BufferedOutputStream fOut = new BufferedOutputStream(
new FileOutputStream(file))) {
byte[] buffer = new byte[32 * 1024];
int bytesRead = 0;
long in = 0;
while ((bytesRead = is.read(buffer)) != -1) {
in += bytesRead;
fOut.write(buffer, 0, bytesRead);
updateProgress(in, max);
}
}
updateMessage("Download Completed Successfully!");
return null;
}
};
Notice the use of the inherited methods updateProgress and updateMessage.
Then you can simply bind the ProgressBar’s properties to your Task’s properties.
progressBar.progressProperty().bind(downloader.progressProperty());
And you can even monitor the Task’s message as it changes:
downloader.messageProperty().addListener(
(o, oldMessage, newMessage) -> pane.appendText("\n" + newMessage));
You’ll probably want to let the user know if the download fails. You can do this with the Task’s onFailed property:
downloader.setOnFailed(e -> {
Exception exception = downloader.getException();
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
TextArea stackTraceField = new TextArea(stackTrace.toString());
stackTraceField.setEditable(false);
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.initOwner(pane.getScene().getWindow());
alert.setTitle("Download Failure");
alert.setHeaderText("Download Failed");
alert.setContextText(
"Failed to download " + link + ":\n\n" + exception);
alert.getDialogPane().setExpandableContent(stackTraceField);
alert.show();
});
Task implements Runnable, so you can start it by passing it to any standard multithreading class:
new Thread(downloader, "Downloading " + link).start();
Or:
CompletableFuture.runAsync(downloader);
Or:
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(downloader);
I have 2 files which are located deep in the android/data system, example of such a file below.
/storage/emulated/0/Android/data/mytest.com.test/files/Documents/Test/Bin/data.dat
I want to copy both of them to a location on the internal storage.
Now stackoverflow is a nice community which has a lot of examples and I therefore searched already for some examples how it is done but unfortunatly it is not working.
Logcat:
V/debug: Copy file failed. Source file missing.
I verified this but the files are definitely there, the destination directory is created but is empty.
Could anybody please assist me?
Main backup method:
public void backupFavorites() {
String folder1, folder2, folder3, folder4;
//Set target directory
String path = Utils.getDownloadDestination(this) + "/FavoritesBackup/Bin/";
File rootPath = new File(path);
if (!rootPath.exists())
rootPath.mkdirs();
//Prepare Sourcefile 1
folder1 = (rootPath + "/" + "data.dat");
File sdcardData = new File (this.getExternalFilesDir
("Documents"), "MyTestApp");
String pathdata = sdcardData.getPath() + "/Bin/data.dat";
File data = new File(pathdata);
//Prepare Sourcefile 2
folder2 = (rootPath + "/" + "trackerdata.dat");
File sdcardTracker = new File(this.getExternalFilesDir
("Documents"), "MyTestApp");
String pathtracker = sdcardTracker.getPath() + "/Bin/trackerdata.dat";
File tracker = new File(pathtracker);
if (trackerDataExists(this)) {
ArrayList<File> sourceFiles = new ArrayList<>();
sourceFiles.add(data);
sourceFiles.add(tracker);
ArrayList<String> destFiles = new ArrayList<>();
destFiles.add(folder1);
destFiles.add(folder2);
for (int i = 0; i < sourceFiles.size(); i++) {
for (int p = 0; p < destFiles.size(); p++) {
try {
copyFiles(sourceFiles.get(i), destFiles.get(p));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Toast.makeText(this, "Backup created", Toast.LENGTH_SHORT).show();
}
}
Code which copies the files:
void copyFiles(File sourceLocation, String targtLocation) throws IOException {
if (sourceLocation.exists()) {
FileInputStream fin = null;
FileOutputStream fout = null;
Log.i("debug", "source " + sourceLocation);
Log.i("debug", "des " + targtLocation);
try {
fin = new FileInputStream(sourceLocation);
new File(String.valueOf(targtLocation)).delete();
fout = new FileOutputStream(targtLocation, false);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Copy the bits from instream to outstream
byte[] buf = new byte[2048];
int len;
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fout);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fin);
while ((len = bufferedInputStream.read(buf)) > 0) {
bufferedOutputStream.write(buf, 0, len);
}
fin.close();
bufferedOutputStream.close();
fout.close();
Log.e("debug", "Copy file successful.");
} else {
Log.v("debug", "Copy file failed. Source file missing.");
}
}
Code to get the download destination:
public static String getDownloadDestination(Context mCon) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mCon);
return pref.getString("downloadFolder", MYDESTINATION.getAbsolutePath());
}
public static final File MYDESTINATION = new File(Environment.getExternalStorageDirectory(),
"Test");
I solved it myself. If anyone encounters the same issue, below is the working code.
public void backupFiles() {
if (DataExists(this)) {
ArrayList<String> sourceFiles = new ArrayList<>();
sourceFiles.add("codex.dat");
sourceFiles.add("ids.dat");
sourceFiles.add("data.dat");
for (int i = 0; i < sourceFiles.size(); i++) {
try {
copyFiles(sourceFiles.get(i));
} catch (IOException e) {
e.printStackTrace();
}
}
Toast.makeText(this, "Backup of FAVORITES created", Toast.LENGTH_SHORT).show();
}
}
public void copyFiles(String sourceLocation) throws IOException {
if (!sourceLocation.isEmpty()) {
FileInputStream fin = null;
FileOutputStream fout = null;
String path = Environment.getExternalStorageDirectory() + Utils.getDownloadDestination
(this) + "/TestBackup/Bin/";
File rootPath = new File(path);
if (!rootPath.exists())
rootPath.mkdirs();
File sdcardData = new File(this.getExternalFilesDir
("Documents"), "MyTest");
String pathdata = sdcardData.getPath() + "/Bin/" + sourceLocation;
File data = new File(pathdata);
Log.i("debug", "source " + pathData);
Log.i("debug", "des " + path + sourceLocation);
try {
fin = new FileInputStream(data);
File outFile = new File(path, sourceLocation);
fout = new FileOutputStream(outFile, true);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fout);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fin);
while ((len = bufferedInputStream.read(buf)) > 0) {
bufferedOutputStream.write(buf, 0, len);
}
fin.close();
bufferedOutputStream.close();
fout.close();
//Comment out to delete originals!
//data.delete();
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.parse(sourceLocation));
sendBroadcast(scanIntent);
Log.e("debug", "Copy file successful.");
} else {
Log.v("debug", "Copy file failed. Source file missing." + sourceLocation);
}
}
I am trying to read a file from a network share using the external jcifs library. Most sample codes I can find for reading files are quite complex, potentially unnecessarily so. I have found a simple way to write to a file as seen below. Is there a way to read a file using similar syntax?
SmbFile file= null;
try {
String url = "smb://"+serverAddress+"/"+sharename+"/TEST.txt";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, username, password);
file = new SmbFile(url, auth);
SmbFileOutputStream out= new SmbFileOutputStream(file);
out.write("test string".getBytes());
out.flush();
out.close();
} catch(Exception e) {
JOptionPane.showMessageDialog(null, "ERROR: "+e);
}
SmbFile file = null;
byte[] buffer = new byte[1024];
try {
String url = "smb://"+serverAddress+"/"+sharename+"/TEST.txt";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, username, password);
file = new SmbFile(url, auth);
try (SmbFileInputStream in = new SmbFileInputStream(file)) {
int bytesRead = 0;
do {
bytesRead = in.read(buffer)
// here you have "bytesRead" in buffer array
}
while (bytesRead > 0);
}
} catch(Exception e) {
JOptionPane.showMessageDialog(null, "ERROR: "+e);
}
or even better, assuming that you're working with text files - using BufferedReader from Java SDK:
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new SmbFileInputStream(file)))) {
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
}
}
And write with:
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new SmbFileOutputStream(file)))) {
String toWrite = "xxxxx";
writer.write(toWrite, 0, toWrite.length());
}
try {
String url = "smb://" + serverAddress + "/" + sharename + "/test.txt";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(DOMAIN, USER_NAME, PASSWORD);
String fileContent = IOUtils.toString(new SmbFileInputStream(new SmbFile(url, auth)), StandardCharsets.UTF_8.name());
System.out.println(fileContent);
} catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
}
I could read some pdf files using this:
private final Singleton<CIFSContext> contextoDdetran = new Singleton<>() {
#Override
public CIFSContext inicializar() {
NtlmPasswordAuthenticator autenticador = new NtlmPasswordAuthenticator(smbDomain, smbUser, smbPassword);
return SingletonContext.getInstance().withCredentials(autenticador);
}
};
public byte[] readSmbFile(String fileName) {
try {
SmbFile file = new SmbFile(fileName, this.contextoDdetran.get());
return file.getInputStream().readAllBytes();
} catch(Exception e) {
final String msgErro = String.format("Error reading file '%s': %s", fileName, e.getMessage());
logger.error(msgErro, e);
throw new IllegalStateException(msgErro);
}
}
I have two node on production environment. I have placed pdf files at one server and want to read it from both server. when am calling 'file' method directly pdf get displayed in browser but when i call 'pdfFiles' nothing is displayed in browser.
public Resolution file(){
try {
final HttpServletRequest request = getContext().getRequest();
String fileName = (String) request.getParameter("file");
File file = new File("pdf file directory ex /root/pdffiles/" + fileName);
getContext().getResponse().setContentType("application/pdf");
getContext().getResponse().addHeader("Content-Disposition",
"inline; filename=" + fileName);
FileInputStream streamIn = new FileInputStream(file);
BufferedInputStream buf = new BufferedInputStream(streamIn);
int readBytes = 0;
ServletOutputStream stream = getContext().getResponse().getOutputStream();
// read from the file; write to the ServletOutputStream
while ((readBytes = buf.read()) != -1)
stream.write(readBytes);
} catch (Exception exc) {
LOGGER.logError("reports", exc);
}
return null;
}
public Resolution pdfFile() {
final HttpServletRequest request = getContext().getRequest();
final HttpClient client = new HttpClient();
try {
String fileName = (String) request.getParameter("file");
final String url = "http://" + serverNameNode1 //having pdf files
+ "/test/sm.action?reports&file=" + fileName;
final PostMethod method = new PostMethod(url);
try {
client.executeMethod(method);
} finally {
method.releaseConnection();
}
} catch (final Exception e) {
LOGGER.logError("pdfReports", "error occured2 " + e.getMessage());
}
return null;
}
Included below part of code after 'client.executeMethod(method);' in 'pdfFile()' method and it works for me.
buf = new BufferedInputStream(method.getResponseBodyAsStream());
int readBytes = 0;
stream = getContext().getResponse().getOutputStream();
// write to the ServletOutputStream
while ((readBytes = buf.read()) != -1)
stream.write(readBytes);
I need to copy and paste dynamically incrementing log file data from FTP Server to local drive.
The below program I used can only do the copying one time. And not in the incremental manner.
public class ReadFtpFile {
public static void main(String[] args) throws UnknownHostException {
String server = "myIP";
int port = 20;
String user = "username";
String pass = "password";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// APPROACH #2: using InputStream retrieveFileStream(String)
String remoteFile2 = "/folder/myfile.log";
File downloadFile2 = new File("F:/myfolder/mylogfile.log");
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
outputStream2.write(bytesArray, 0, bytesRead);
}
Boolean success = ftpClient.completePendingCommand();
if (success) {
System.out.println("File #2 has been downloaded successfully.");
}
outputStream2.close();
inputStream.close();
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
The log file data in the FTP server is growing for every second.I need to update the local file with new data in the FTP.
Replace the lines
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
with
ftpClient.setRestartOffset(downloadFile2.length());
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2, true));
This will check if the file already exists and, if so, download only the new data. If you need to do this periodically, add a loop around the whole try-catch block.
You need to update your code with Java threads and combine while loops to schedule this program for desired time.
String remoteFile2 = "/folder/myfile.log";
File downloadFile2 = new File("F:/myfolder/mylogfile.log");
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
int minutecount=0;
while(minutecount==120){
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
outputStream2.write(bytesArray, 0, bytesRead);
}
// Here i sceduled for every 1 minute
Thread.sleep(60*1000);
minutecount++;
}
Boolean success = ftpClient.completePendingCommand();
if (success) {
System.out.println("File #2 has been downloaded successfully.");
}
outputStream2.close();
inputStream.close();`