Learn to upload multipart binary file (e.g. jpeg image) with a Spring REST API accepting MultipartFile request. Also learn to download file using another REST API using FileSystemResource.
1. Maven dependency
Apart from spring webmvc, we will need
commons-fileupload
and commons-io
in classpath.dependency> < groupId >org.springframework</ groupId > < artifactId >spring-webmvc</ artifactId > < version >5.1.6.RELEASE</ version > </ dependency > < dependency > < groupId >commons-fileupload</ groupId > < artifactId >commons-fileupload</ artifactId > < version >1.4</ version > </ dependency > < dependency > < groupId >commons-io</ groupId > < artifactId >commons-io</ artifactId > < version >2.6</ version > </ dependency > |
2. Configure CommonsMultipartResolver
It is Servlet-based
MultipartResolver
implementation for commons-fileupload
. It provides “maxUploadSize“, “maxInMemorySize” and “defaultEncoding” settings as bean properties.
The purpose of this class is to save the temporary files to the servlet container’s temporary directory.
< beans > ... < bean id = "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" > < property name = "maxUploadSize" value = "100000" /> </ bean > ... </ beans > |
3. Create multipart handler apis
Create two REST APIs which will responsible for handling upload and download requests and responses. It given example, I have created APIs at path
/employee-management/employees/1/photo
.
I am assuming at employee with id
'1'
exist in database. Feel free to change the resource path and implementation.package com.howtodoinjava.demo.controller; import static org.springframework.web.servlet .support.ServletUriComponentsBuilder.fromCurrentRequest; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.util.concurrent.Callable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.howtodoinjava.demo.exception.RecordNotFoundException; import com.howtodoinjava.demo.model.Employee; import com.howtodoinjava.demo.repository.EmployeeRepository; @RestController @RequestMapping (value = "/employee-management/employees/{id}/photo" ) @PropertySource ( "classpath:application.properties" ) public class EmployeeImageController { @Autowired private EmployeeRepository repository; private File uploadDirRoot; @Autowired EmployeeImageController( @Value ( "${image.upload.dir}" ) String uploadDir, EmployeeRepository repository) { this .uploadDirRoot = new File(uploadDir); this .repository = repository; } @GetMapping ResponseEntity<Resource> read( @PathVariable Long id) { return this .repository.findById(id) .map(employee -> { File file = fileFor(employee); Resource fileSystemResource = new FileSystemResource(file); return ResponseEntity.ok() .contentType(MediaType.IMAGE_JPEG) .body(fileSystemResource); }) .orElseThrow(() -> new RecordNotFoundException( "Image for available" )); } @RequestMapping (method = { RequestMethod.POST, RequestMethod.PUT }, consumes = { "multipart/form-data" }) Callable<ResponseEntity<?>> write( @PathVariable Long id, @RequestParam ( "file" ) MultipartFile file) throws Exception { return () -> this .repository.findById(id) .map(employee -> { File fileForEmployee = fileFor(employee); try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileForEmployee)) { FileCopyUtils.copy(in, out); } catch (IOException ex) { throw new RuntimeException(ex); } URI location = fromCurrentRequest().buildAndExpand(id).toUri(); return ResponseEntity.created(location).build(); }) .orElseThrow(() -> new RecordNotFoundException( "Employee id is not present in database" )); } private File fileFor(Employee e) { return new File( this .uploadDirRoot, Long.toString(e.getId())); } } |
Above REST controller relies on existence of upload folder configured in properties file i.e.
image.upload.dir
.image.upload.dir=c:/temp/images |
Also, the controller returns the Callable which means the method returns immediately while the IO operations may run. Once the upload process is finished, API returns the response. To enable async support, configure async-supported in
DispatcherServlet
.< web-app > < display-name >Employee Management REST APIs</ display-name > < servlet > < servlet-name >rest</ servlet-name > < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class > < load-on-startup >1</ load-on-startup > < async-supported >true</ async-supported > </ servlet > < servlet-mapping > < servlet-name >rest</ servlet-name > < url-pattern >/api/rest/*</ url-pattern > </ servlet-mapping > </ web-app > |
4. Multipart upload request demo
For demo purpose, I have created a JSP page with only single field of type file. We will browse a image from computer, and upload it to server.
< html > < head > < title >Spring REST File Upload</ title > </ head > < body > < form method = "POST" action = "/SpringRestExample/api/rest/employee-management/employees/1/photo" enctype = "multipart/form-data" > < table > < tr > < td >Select a file to upload</ td > < td >< input type = "file" name = "file" /></ td > </ tr > < tr > < td >< input type = "submit" value = "Submit" /></ td > </ tr > </ table > </ form > </ body > </ html > |
Now start the server and open the upload page in URL
http://localhost:8080/SpringRestExample/singleFileUpload.jsp
. Browser the file and click on Submit button. The image file will be uploaded to server in configured upload directory.
To download the file, enter the URL
/employee-management/employees/1/photo
in browser and image will be displayed.
No comments:
Post a Comment