2

I have a problem. I want to convert BufferedImage to the MultipartFile. First, on my UI I sent base64 to the server, and on my server, I convert to the BufferedImage after that I want to convert BufferedImage to the MultipartFile and save on the local storage. This is my method:

@PostMapping("/saveCategory")
    @ResponseStatus(HttpStatus.OK)
    public void createCategory(@RequestBody String category ) {



        BufferedImage image = null;
        OutputStream stream;
        byte[] imageByte;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            imageByte = decoder.decodeBuffer(category);
            ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
            image = ImageIO.read(bis);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    String fileName = fileStorageService.storeFile(image );

My storage method:

public String storeFile(MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        try {
            // Check if the file's name contains invalid characters
            if (fileName.contains("..")) {
                throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Path targetLocation = this.fileStorageLocation.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return fileName;
        } catch (IOException ex) {
            System.out.println(ex);
            throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);

        }
    }
SIn san sun
  • 573
  • 4
  • 13
  • 31

1 Answers1

9

Such conversion from base64 to MultipartFile is done by Spring automatically. You just need to use correct annotations.

You can create a wrapper dto class holding all necessary data.

public class FileUploadDto {
    private String category;
    private MultipartFile file;
    // [...] more fields, getters and setters
}

Then you can use this class in your controller:

@RestController
@RequestMapping("/upload")
public class UploadController {

    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);

    @PostMapping
    public void uploadFile(@ModelAttribute FileUploadDto fileUploadDto) {
        logger.info("File upladed, category= {}, fileSize = {} bytes", fileUploadDto.getCategory(), fileUploadDto.getFile().getSize());
    }

}

The reason I didn't get the point of the question on a first glance was @RequestBody String category. I think this is a very very misleading variable name for a file. However, I created the DTO class with the category field aswell so you could include it in your request.

Of course, then you get rid of your controller logic and simply call the service method like fileStorageService.storeFile(fileUploadDto.getFile()); or pass the whole file and make use of category field.

edit

I also include the request sent from Postman and some console output:

Postman request and console output

Community
  • 1
  • 1
Pijotrek
  • 2,821
  • 1
  • 18
  • 32
  • Thanks, this is useful. I appreciate that. This is a good start point for beginners. – SIn san sun Feb 28 '19 at 10:54
  • glad it helped! – Pijotrek Feb 28 '19 at 11:03
  • I have another problem because I want to send category, file, and product like JSON object and bind in my model. I think is not possible to send an object together with MultipartFIle? – SIn san sun Feb 28 '19 at 11:05
  • Of course it is, you can add as many fields as you wish in your DTO class. – Pijotrek Feb 28 '19 at 11:10
  • Hmm, ok. `public class FileUploadDto { private String category; private MultipartFile file; private CategoryModel model;` And I from my POSTMAN sand this for model `{ "category_name": "sd"}` and I have error. – SIn san sun Feb 28 '19 at 11:13
  • Is it ENUM or a POJO class? If it's enum it should work without any problems, if it's a class then I think you'll have to work it out other way. – Pijotrek Feb 28 '19 at 11:23
  • This is my CategoryModel class: `@Entity @Table(name = "Category") @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" }) public class CategoryModel { @Id @Column(name = "id") //@GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String category_name; private String category_description; private String image_path; @JsonIgnore @OneToMany( mappedBy = "category") private Set category;` It is posible to do with this model? – SIn san sun Feb 28 '19 at 11:26
  • you can create fields accordingly in your DTO then map them to your entity class – Pijotrek Feb 28 '19 at 11:31
  • Do you have any example? This will be very useful for me. – SIn san sun Feb 28 '19 at 12:46
  • @Pijotrek WHen I change RequestBody to ModelAttribute then my object in my endpoint is empty. Why? – Matley Nov 27 '20 at 12:51