Uploading files on filesystem spring boot

In this article, I’ll show you a very simple way to upload and save your file in the filesystem rather than saving as a blob in the database.
It’ll be a very flexible way to do that. We can provide a root path for a filesystem (aws or other service, or our servers file system) where it’ll consider saving files.

1. Create a Pojo for keeping the file informations

public class UploadProperties {
    private String namespace;
    private String uniqueProperty;
    private String rootPath;
    private String fileName;

    public enum NameSpaces{
        USERS("users"),
        COMPANIES("companies");

        String value;

        NameSpaces(String value){
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }

    public String getDirPath() {
        if (namespace == null || namespace.isEmpty()
                || uniqueProperty == null || uniqueProperty.isEmpty()
                || rootPath == null || rootPath.isEmpty())
            throw new IllegalArgumentException("Rootpath or uniqueProperty or Namespace can not be null or empty!");
        return rootPath + File.separator + "AppData" + File.separator + namespace
                + File.separator + uniqueProperty + File.separator + "images";
    }

    public String getFilePath() {
        if (fileName==null|| fileName.isEmpty())
            throw new IllegalArgumentException("Filename can not be null or empty!");
        return getDirPath() + File.separator + fileName;
    }

   // Getters and setters
}

2. Create a service to upload files

@Service
public class FileUploadServiceImpl implements FileUploadService {

    @Value("${files.upload.path}")
    private String rootPath;

    @Override
    public UploadProperties uploadFile(MultipartFile multipartFile, String namespace, String uniqueProperty) throws IOException {
        byte[] bytes = multipartFile.getBytes();

        UploadProperties uploadProperties = new UploadProperties();
        uploadProperties.setNamespace(namespace);
        uploadProperties.setUniqueProperty(uniqueProperty);
        uploadProperties.setRootPath(rootPath);

        File directory = new File(uploadProperties.getDirPath());
        if (!directory.exists()) {
            directory.mkdirs();
        }
        File imageFile = File.createTempFile("upload_", ".png", directory);
        OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(imageFile));
        outputStream.write(bytes);
        outputStream.close();

        uploadProperties.setFileName(imageFile.getName());
        return uploadProperties;
    }
}
Here, the namespace property we are taking to provide a unique path for a specific entity or module. Suppose of have two types of actors in our system, users and companies. So we can set namespace /company if we are going to save company logo or something like that. and /users for saving user informations. The main purpose if to seperate files for some high level modules.
​​uniqueProperty is to save data to a unique folder for a unique user. We can pass  username for instance, so that we can in the future, get files for that user with his/her username. they are just for the convenience, to organize in a specific manner.

3. Upload file

Create a controller to upload file and save it to filesystem using fileUploadService

@PostMapping("/{userId}/uploadPhoto")
public String uploadPhoto(@Valid @ModelAttribute("userId") Long userId, BindingResult bindingResult,
                                  @RequestParam(value = "profilePicture", required = false) MultipartFile multipartFile,
                                   ) throws IOException {

    if (bindingResult.hasErrors()) {
        System.out.println(bindingResult.toString());
    }
    // set image
    if (ImageValidator.isImageValid(multipartFile)) {
        User user = this.userService.find(userId);
        UploadProperties properties = this.fileUploadService.uploadFile(multipartFile, UploadProperties.NameSpaces.USERS.getValue(), person.getPhoneNumber());
        user.setProfilePicturePath(properties.getFilePath());
        this.userService.save(user);
    }
   return "redirect:/users/"+userId;
}

4. Downloading/Showing image/file

// returns image with that entity id
@RequestMapping(value = "/images/{personId}", method = RequestMethod.GET)
private ResponseEntity<byte[]> getImage(@PathVariable("userId") Long userId) throws IOException {
    User user = this.userService.find(userId);
    if (user == null) return ResponseEntity.ok();
    File file = new File(user.getProfilePicturePath());
    if (!file.exists()) return ResponseEntity.noContent().build();
    return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(FileUtils.readFileToByteArray(file));
}
Please let me know if you face any problem.

Leave a Reply

Your email address will not be published. Required fields are marked *