How to convert FTP from Spring MVC to Spring Boot/Thymeleaf? - java

So I've been working on taking the logic from an older webapp and making a new Spring Boot application out of it. I've come to a stuck spot regarding an ftp connection and call. Since I don't have a bunch of experience with this, I'm curious if there is a better/more modern way to handle most of this ftp stuff using Spring Boot/Thymeleaf and ways to go ahead and set that up. Any advice/guidance would be fantastic.
This is the older code that I'd like to modernize a bit.
String serverName = getFtpServer();
// Connect to the server
try {
ftp.connect(serverName);
ftp.enterLocalPassiveMode();
String replyText = ftp.getReplyString();
System.out.println(replyText);
} catch (Exception e) {
e.printStackTrace();
return false;
}
// Login to the server
try {
ftp.login(userName, password);
String replyText = ftp.getReplyString();
System.out.println(replyText);
} catch (Exception e) {
e.printStackTrace();
return false;
}
// Tell server that the file will have JCL records
try {
ftp.site("filetype=jes");
String replyText = ftp.getReplyString();
System.out.println(replyText);
} catch (Exception e) {
e.printStackTrace();
return false;
}
// Submit and run the JCL
try {
System.out.println("TRYING TO START MAINFRAME JCL");
submitJcl(filename, serverName);
String replyText = ftp.getReplyString();
System.out.println(replyText);
} catch (Exception e) {
String replyText = ftp.getReplyString();
System.out.println(replyText);
e.printStackTrace();
return false;
}
// Quit the server
try {
ftp.quit();
} catch (Exception e) {
e.printStackTrace();
}
Storing the file
private String submitJcl(String remoteFile, String serverName) throws IOException {
String filePath = getFilePath();
String result = "";
String fileName = filePath + remoteFile;
System.out.println("filePath = " + fileName);
FileInputStream inputStream = new FileInputStream(fileName);
ftp.storeFile(serverName, inputStream);
return result;
}

For this I figured out that there may be better ways to change it into the newer ftp format for Spring Boot, but this still completely works.
Changes I made to it regardless:
Consolidated the try/catch blocks into one.
Pushed the ftp stuff into its own function and then just called it inside the try/catch block
Changed all of the sys.out's to info.debugs.
Changed the way it gets the filePath to more of a relative path with the file stored within the system instead of user files.

Related

FTPClient connection with Java on AWS Virtual Machine

I'm trying to connect to my FTP server in Java SE 1.8. To do so I use this method :
private void connectFTP() {
String server = "ftp.XXXXXXXXXX.site";
int port = 21;
String user = "XXXX";
String pass = "XXXX";
if(!ftpConnexionSuccess.get())
{
client = new FTPClient();
client.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX));
try {
client.connect(server, port);
ftpConnexionSuccess.set(client.login(user, pass));
if (!ftpConnexionSuccess.get()) {
System.out.println("Could not login to the server");
return;
}
else
{
System.out.println("LOGGED IN SERVER");
client.changeWorkingDirectory("/crypto");
listenedFile = getListenedFile();
System.out.println(listenedFile.getName());
if(listenedFile != null)
{
baseFileTimeStamp.set(listenedFile.getTimestamp().getTimeInMillis());
}
System.out.println(baseFileTimeStamp);
}
} catch (Exception ex) {
System.err.println("FTP connection error : Sleeping for 5 seconds before trying again (" + ex.getMessage() + ")");
ex.printStackTrace();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {e.printStackTrace();}
try {
client.disconnect();
} catch (IOException e) {e.printStackTrace();}
connectFTP();
}
}
}
It works great when I'm on Eclipse and when I export the app on my Windows 10.
Nonetheless, when I try to launch the app on my AWS Webmachine I get a null pointer exception at "listenedFile". The method to listen to this file is the one below.
private FTPFile getListenedFile() {
FTPFile returnedFile = null;
try {
for(FTPFile file : client.listFiles())
{
if(file.getName().contains("filetolisten.txt"))
returnedFile = file;
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
try {
client.disconnect();
} catch (IOException e1) {e1.printStackTrace();}
connectFTP();
return getListenedFile();
}
return returnedFile;
}
I thought it was because of the line
client.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX));
I tried to delete the line, and to replace SYST_UNIX with SYST_NT, but nothing worked.
I tried to delete the line, and to replace SYST_UNIX with SYST_NT, but nothing worked. Also updated Java, updated the common-nets library. Nothing worked

Springboot async upload and store method using multipart file problem

I am trying to make async upload service with spring boot, here is my code:
public ResponseEntity<?> save(MultipartFile[] files) {
if (files.length == 0) {
return ResponseEntity.badRequest().body("No files selected");
}
DigikyblikFileStorage storage = digikyblikFileStoragesService.getIdealStorage();
UUID bucketUUID = UUID.randomUUID();
asyncService.saveFiles(files, storage, bucketUUID);
try {
List<File> filesData = new ArrayList<>();
for (MultipartFile file : files) {
filesData.add(new File(file.getOriginalFilename(), file.getSize()));
}
BucketFilesRecord record = new BucketFilesRecord();
record.setBucketUUID(bucketUUID);
record.setStorageId(storage.getId());
record.setFilesInfo(new ObjectMapper().writeValueAsString(filesData));
bucketFilesRecordRepository.save(record);
} catch (JsonProcessingException e) {
logger.error("Error when setting files info for bucketUUID: " + bucketUUID, e);
return ResponseEntity.internalServerError().body("Error when setting files info for bucketUUID: " + bucketUUID);
} catch (IOException e) {
logger.error("Error when getting bytes from multipart files for bucketUUID: " + bucketUUID, e);
}
return new ResponseEntity<>(new FilesUploadedResponse(bucketUUID), HttpStatus.OK);
}
and :
#Async
public void saveFiles(MultipartFile[] files, DigikyblikFileStorage storage, UUID bucketUUID) {
logger.info("Start storing files for bucketUUID: " + bucketUUID);
Path filesPath = Paths.get(storage.getStoragePath() + java.io.File.separator + bucketUUID);
try {
Files.createDirectories(filesPath);
} catch (IOException e) {
logger.error("Couldn't create directories for bucketUUID: " + bucketUUID, e);
return;
}
for (MultipartFile file : files) {
Path path = Paths.get(filesPath + java.io.File.separator + file.getOriginalFilename());
try {
file.transferTo(path);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Sometimes it works well, but sometimes i get this error:
java.nio.file.NoSuchFileException: /media/wedos-test/upload_814fc87f_9641_48be_adb4_c79f0111f11c_00000012.tmp
I know why, its because that spring delete tmp folder before file transaction is done, but i dont know how this could be repared, one solution was that a could read bytes and then call async method, so tmp directory shouldnt be needed anymore, but when i try upload bigger files with this solution, i get of course memory error. Can anyone help me with this problem? Thanks!
I think the second comment from that answer could help you. It says that you can create your own temp file on disk and work with it while needed. In that scenario you don't need to think about memory.
And take a look at approach number 2. It suggests to use MultiPartFile implementation with custom constructor and then use it in your logic.

Apache commons FPTSClient explicit transfer file is incomplete

Iam currently struggling a little bit with the FTPSClient from Apache Commons. See code down below. I try to write a file to FTP Server (vsftpd) when using FTPClient things are working perfectly fine. When using my code snippet I will always get a 451 Error, when debugging and waiting after Util.copyStream() returned everything works fine or settings a Thread.sleep(100). This also does not happen when I do not set the ftpsClient.execProt("P). Does anyone know by what this could be caused.
final FTPSClient client;
client = new FTPSClient("TLS", false);
client.setUseClientMode(true);
client.setDefaultPort(21);
// connect
try {
client.connect("serverAddress", 21);
} catch (SSLException e) {
throw e;
}
// setup any after connected
client.setSoTimeout(300);
client.setListHiddenFiles(true);
client.enterLocalPassiveMode();
FTPClientConfig ftpConfig;
try {
ftpConfig = new FTPClientConfig(client.getSystemType());
} catch (FTPConnectionClosedException e) {
throw e;
} catch (IOException e) {
ftpConfig = new FTPClientConfig();
}
client.configure(ftpConfig);
final FTPSClient ftpsClient = client;
// remove data buffer limit
ftpsClient.execPBSZ(0);
// set data channel encrypted
ftpsClient.execPROT("P");
client.login("user", "password");
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
throw new IOException("Authentication failed: " + client.getReplyString().trim());
}
// postconfigure connection
if (!client.setFileTransferMode(FTP.STREAM_TRANSFER_MODE) || !client.setFileType(FTP.BINARY_FILE_TYPE)) {
throw new IOException("Failed to correctly configure client: " + client.getReplyString().trim());
}
InputStream input;
OutputStream output;
input = new FileInputStream(pathToLocalFile);
output = client.storeFileStream("foobar.txt");
final var number = Util.copyStream(input, output);
System.out.println(number);
input.close();
// Thread.sleep(100);
output.close();
// Must call completePendingCommand() to finish command.
if (!client.completePendingCommand()) {
client.logout();
client.disconnect();
System.err.println("File transfer failed.");
}
This library has been around for a long time, and things change a bit under the hood. Try:
input = new FileInputStream(pathToLocalFile);
boolean result = client.storeFile("foobar.txt", input);
if (result) {
System.out.println("\tFile Transfer Completed Successfully");
}
I have noticed that every once in a while when transferring files to a mainframe, it won't complete. I think it has something to do with the file length, but I've never been able to track it down. I also don't use the stream_transfer_mode.

Learning handling exceptions, can't figure out this FileNotFoundException

I'm a beginner still, and currently learning about handling exceptions. The exercise in my book I'm trying to figure out tells me to add a Finally block to close out the file I opened, and I don't understand what I'm doing wrong. Keep in mind the file name and path are fake but here is what I have:
public static String readLineWithFinally()
{
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = new RandomAccessFile("products.ran", "r");
try
{
String s = in.readLine();
return s;
}
catch (IOException e)
{
System.out.println(e.toString());
return null;
}
finally
{
try
{
in.close();
}
catch (Exception e)
{
System.out.println("Generic Error Message");
}
}
}
To add on to Taylor Hx's answer, you can take advantage of Java 7's try-with-resources construct to avoid having to use finally altogether in your case.
public static String readLineWithFinally() {
System.out.println("Starting readLineWithFinally method.");
try (RandomAccessFile in = new RandomAccessFile("products.ran", "r")) {
return in.readLine();
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
You'll also want to be certain that your usage is consistent with what the API mandates for RandomAccessFile.
The code that you posted shouldn't compile, as RandomFile(String, String) can possibly throw FileNotFoundException. As such, we must include it in the try block.
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = null;
try {
in = new RandomAccessFile("products.ran", "r");
String s = in.readLine();
return s;
} catch (IOException e) {
System.out.println(e.toString());
return null;
} finally {
try {
if(in != null) {
in.close();
}
} catch (Exception e) {
System.out.println("Generic Error Message");
}
}
Keep in mind the file name and path are fake but here is what I have:
That is why you will have a FileNotFoundException while creating RandomAccessFile("products.ran", "r") with read access mode "r".
From the documentation: RandomAccessFile(String name, String mode)
This constructor throws a FileNotFoundException if the mode is
"r" but the given string does not denote an existing regular file,
or if the mode begins with "rw" but the given string does not denote
an existing, writable regular file and a new regular file of that name
cannot be created, or if some other error occurs while opening or
creating the file

FTP File upload using Java

hey i want to upload a file to a directory called 'screenshots' on my webserver via FTP using java. I have been using this code and it says that it stores the file successfully and connected successfully but when i check my screenshots directory via the cpanel i dont see the file that was uploaded any help?
public static void uploadFilee() {
FTPClient client = new FTPClient();
FileInputStream fis = null;
try {
client.connect("****************");
client.login("********", "********");
System.out.println("Connected Successfully");
String filename = "C:/Users/Christian/Desktop/screenshots/img_" + queueInfo.get("SessionID");
fis = new FileInputStream(filename);
client.storeFile(filename, fis);
System.out.println("Stored File Successfully");
client.logout();
} catch (IOException e) {
System.out.println("Error_1");
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
client.disconnect();
} catch (IOException e) {
System.out.println("Error_2");
e.printStackTrace();
}
}
}
`
You may want to review this page
http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#_storeFile(java.lang.String,java.lang.String,java.io.InputStream)
you have your statements such as storefile in a try statement, but if they fail, they return false, not an exception.
changing your code to inspect the return values of each function should help you find where your problem lies.

Categories