0

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!

Sizor
  • 17
  • 4

1 Answers1

0

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.

Alex A
  • 33
  • 5