-
Notifications
You must be signed in to change notification settings - Fork 0
Multipart File Upload Download Rest API
Multipart file Upload link
File Storage Properties:
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
## File Storage Properties
# All files uploaded through the REST API will be stored in this directory
file.upload-dir=./uploadsAutomatically binding properties to a POJO class:
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
// Setter & Getters ...
}Enable Configuration Properties:
Now, To enable the ConfigurationProperties feature, you need to add @EnableConfigurationProperties annotation to any configuration class.
@SpringBootApplication
@EnableConfigurationProperties({
FileStorageProperties.class
})
public class FileDemoApplication {
public static void main(String[] args) {
SpringApplication.run(FileDemoApplication.class, args);
}
}Writing APIs for File Upload and Download:
@RestController
public class FileController {
private static final Logger logger = LoggerFactory.getLogger(FileController.class);
@Autowired
private FileStorageService fileStorageService;
@PostMapping("/uploadFile")
public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) {
String fileName = fileStorageService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName)
.toUriString();
return new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize());
}
@PostMapping("/uploadMultipleFiles")
public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
return Arrays.asList(files)
.stream()
.map(file -> uploadFile(file))
.collect(Collectors.toList());
}
@GetMapping("/downloadFile/{fileName:.+}")
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
// Load file as Resource
Resource resource = fileStorageService.loadFileAsResource(fileName);
// Try to determine file's content type
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
public class UploadFileResponse {
private String fileName;
private String fileDownloadUri;
private String fileType;
private long size;
public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) {
this.fileName = fileName;
this.fileDownloadUri = fileDownloadUri;
this.fileType = fileType;
this.size = size;
}
// Getters and Setters (Omitted for brevity)
}@Service
public class FileStorageService {
private final Path fileStorageLocation;
@Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
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) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public Resource loadFileAsResource(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if(resource.exists()) {
return resource;
} else {
throw new MyFileNotFoundException("File not found " + fileName);
}
} catch (MalformedURLException ex) {
throw new MyFileNotFoundException("File not found " + fileName, ex);
}
}
}We get an exception as org.springframework.web.multipart.MultipartException: Current request is not a multipart request
http://localhost:8080/uploadfile
Headers:
[{"key":"content-type","value":"application/x-www-form-urleconded","description":""}]
Body:
[{"key":"file","value": Raw file Source from locak disk}]
Response:
{
"timestamp": 1549282441115,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.web.multipart.MultipartException",
"message": "Current request is not a multipart request",
"path": "/uploadfile"
}
On removing the content-type:application/x-www-form-urleconded it is working fine...
Spring Boot is a project that is built on the top of the Spring Framework. It provides an easier and faster way to set up, configure, and run both simple and web-based applications. It is a Spring module that provides the RAD (Rapid Application Development) feature to the Spring Framework.
