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.
Related
I am trying to understand why my code won't run.
The example is how to use java.io to find a path directory and print out the title of all .txt files in that directory.
My code is below:
try
{
Files.walk(Paths.get(\\Users\\Name\\Desktop\\Test Folder)).forEach(p -> {
if (p.getFileName().toString().endsWith(".txt")) {
System.out.println("Text doc: " + p.getFileName());
}
});
} catch (IOException e) {
e.printStackTrace();
}
I am currently importing java.io.IOException, java.nio.file.Files, and java.nio.file.Paths.
The error I am getting is java.nio.file.NoSuchFileException: myDirPath.
If anyone can help, or at least point me in the right direction I would be very grateful.
try
{
Files.walk(Paths.get("/Users/Jayden/Desktop/Test Folder")).forEach(p -> {
if (p.getFileName().toString().endsWith(".txt")) {
System.out.println("Text doc: " + p.getFileName());
}
});
} catch (IOException e) {
e.printStackTrace();
}
I was not using slashes properly.
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.
Everyone keeps saying how simple it is to move a file from point a to point b using fileutils, but I'm having lots of trouble moving a file :(
I have a /temp/ folder in the directory wherever the .jar is located, in this temp folder I have a .txt file I want to move up a directory (so basically next to the .jar file) but I cant seem to do it?
Here's some code, but I know its not even close:
public void replaceFile() {
String absolutePath = getPath();
Path from = Paths.get(absolutePath + "\\temp\\test.txt");
Path to = Paths.get(absolutePath + "\\test.txt");
try {
FileUtils.moveFile(FileUtils.getFile(from.toAbsolutePath().toString()), FileUtils.getFile(to.toAbsolutePath().toString()));
JOptionPane.showMessageDialog(null, "test");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getPath() {
File jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath());
//JOptionPane.showMessageDialog(null, jarDir.getAbsolutePath());
return jarDir.getAbsolutePath();
}
Any help is appreciated :\
Why don't use this Java API for Moving a File or Directory
Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
UPDATE
Looking at your source code I suggest the following implementation:
Path from = Paths.get(absolutePath, "/temp/test.txt");
Path to = Paths.get(absolutePath, "/test.txt");
try {
Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
JOptionPane.showMessageDialog(null, "test");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ok i managed to do it, apparently the getPath() method returned some funny path and it failed there, so heres a code that works
public void downloadJar() {
String absolutePath = getPath();
String from = absolutePath + "\\temp\\test.txt";
String to = absolutePath + "\\test.txt";
File fileTo = new File(to);
File fileFrom = new File(from);
try {
FileUtils.moveFile(fileFrom, fileTo);
JOptionPane.showMessageDialog(null, "test");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
JOptionPane.showMessageDialog(null, "io exce");
}
}
public String getPath() {
return System.getProperty("user.dir");
}
thanks everyone
I am using Jackcess API in my Eclipse plugin project. I added jackcess-2.1.0.jar file under resources/lib. I included the jar under my Binary build and in build.properties. I successfully make a connection using connection string but my DatabaseBuilder.open() call is not executing. My code is
public void run() {
try {
File tempTarget = File.createTempFile("eap-mirror", "eap");
try {
this.source = DriverManager.getConnection(EaDbStringParser.eaDbStringToJdbc(sourceString));
this.source.setReadOnly(true);
try {
FileUtils.copyFile(new File(templateFileString), tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
// Changes
try {
this.target = DatabaseBuilder.open(tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
Collection<String> tables = selectTables(source);
long time = System.currentTimeMillis();
for (String tableName : tables) {
long tTime = System.currentTimeMillis();
Table table = target.getTable(tableName);
System.out.print("Mirroring table " + tableName + "...");
table.setOverrideAutonumber(true);
copyTable(table, source, target);
System.out.println(" took "+ (System.currentTimeMillis() - tTime));
}
System.out.println("Done. Overall time: "+ (System.currentTimeMillis() - time));
System.out.println("done");
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// More Code here
} catch (IOException e1) {
}
}
When I run the class in debug mode and I reach DatabaseBuilder.open call it fails.
Here is my project structure:
Can anyone tell me the possible reason for it ?
The .open method of DatabaseBuilder expects to open an existing well-formed Access database file. The .createTempFile method of java.io.File creates a 0-byte file. So, the code
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", "eap");
try (Database db = DatabaseBuilder.open(dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}
will cause Jackcess to throw
java.io.IOException: Empty database file
when it tries to do DatabaseBuilder.open(dbFile).
Instead, you should DatabaseBuilder.create to convert the 0-byte file into a real Access database file like this
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", ".accdb");
dbFile.deleteOnExit();
try (Database db = DatabaseBuilder.create(Database.FileFormat.V2010, dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}
So, I have a function that reads file data, in this case image size. But after it's done it doesn't seem to properly release the files. I can't move those files afterwards. If I don't call this function everything works, but if I do I always get "file in use.. blah blah blah"
private void setMoveType() {
ImageInputStream in = null;
try {
in = ImageIO.createImageInputStream(new FileInputStream(file.toString()));
try {
final Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
if(readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(in);
try {
moveType = Helper.getMoveType(new Dimension(reader.getWidth(0), reader.getHeight(0)));
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
return;
}
} catch(Exception e) {
System.err.println("ReaderException: " + e.getMessage());
} finally {
reader.dispose();
}
}
} catch(Exception e) {
System.err.println("MoveTypeSetException: " + e.getMessage());
}
} catch (IOException e) {
System.err.print("IOException: failure while creating image input stream");
System.err.println(" -> createImageInputStream Error for file: " + file.getFileName());
return;
} finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
return;
}
}
}
}
EDIT: The ImageInputStream doesn't close properly
EDIT2: a FileInputStream wasn't closed
This stream should also be closed:
new FileInputStream(file.toString())
Closing the stream when you are done should work (in.close()). The operating system prevents the file from being changed, deleted or moved while it is in use. Otherwise, the stream would get messed up. Closing the stream tells the operating system you are no longer using the file.