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.
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.