{ "fileName": "Photo.jpg", "downloadUri": "/downloadFile/AE7GPzg1", "size": 13573 }Note that the alphanumeric string at the end of the downloadUri field is the file code which is used in file download API.And below is description of the file download API:- End point URI: /downloadFile/{fileCode}- HTTP method: GET- Response status: + NOT_FOUND if no file found for the given file code + METHOD_NOT_ALLOWED if the request method is not POST + INTERNAL_SERVER_ERROR if any IO error occurs on the server + OK if a file found and the response contains file data
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency>The spring-boot-starter-web dependency is enough for implementing RESTful webservices and multipart file upload functionality. And the commons-lang3 dependency is for using a utility class that generate random alphanumeric strings (used as file identifier or file code).
package net.codejava.upload; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.web.multipart.MultipartFile; public class FileUploadUtil { public static String saveFile(String fileName, MultipartFile multipartFile) throws IOException { Path uploadPath = Paths.get("Files-Upload"); if (!Files.exists(uploadPath)) { Files.createDirectories(uploadPath); } String fileCode = RandomStringUtils.randomAlphanumeric(8); try (InputStream inputStream = multipartFile.getInputStream()) { Path filePath = uploadPath.resolve(fileCode + "-" + fileName); Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException ioe) { throw new IOException("Could not save file: " + fileName, ioe); } return fileCode; } }You see, in the saveFile() method, it creates the Files-Upload directory if not exists to store the uploaded files. And it inserts 8 alphanumeric characters before the file name, so in the file download API it can identify a file based on an identifier.Finally, the method returns the fileCode which is then used in download URI field of the response body.
package net.codejava.upload; import java.io.IOException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @RestController public class FileUploadController { @PostMapping("/uploadFile") public ResponseEntity<FileUploadResponse> uploadFile( @RequestParam("file") MultipartFile multipartFile) throws IOException { String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename()); long size = multipartFile.getSize(); String filecode = FileUploadUtil.saveFile(fileName, multipartFile); FileUploadResponse response = new FileUploadResponse(); response.setFileName(fileName); response.setSize(size); response.setDownloadUri("/downloadFile/" + filecode); return new ResponseEntity<>(response, HttpStatus.OK); } }You see, the handler method uploadFile() requires a multipart in the request have the name “file”. Spring MVC uses Java Servlet API to handle file uploaded from the client behind the scene. So we just need to write code that saves the file to a specific directory on disk.And you can notice, it puts a FileUploadResponse object into the response body. So code the FileUploadResponse class as follows:
package net.codejava.upload; public class FileUploadResponse { private String fileName; private String downloadUri; private long size; // getters and setters are not shown for brevity }Spring Web MVC will serialize this object, which results in a JSON document sent to the client - as required by the API description.
Spring Boot REST APIs Ultimate Course
Hands-on REST API Development with Spring Boot: Design, Implement, Document, Secure, Test, Consume RESTful APIs
package net.codejava.upload; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; public class FileDownloadUtil { private Path foundFile; public Resource getFileAsResource(String fileCode) throws IOException { Path dirPath = Paths.get("Files-Upload"); Files.list(dirPath).forEach(file -> { if (file.getFileName().toString().startsWith(fileCode)) { foundFile = file; return; } }); if (foundFile != null) { return new UrlResource(foundFile.toUri()); } return null; } }You see, the method getFileAsResource requires a String parameter fileCode that acts as an identifier. It returns a Resource object if a matching file is found, or null otherwise.
package net.codejava.upload; import java.io.IOException; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class FileDownloadController { @GetMapping("/downloadFile/{fileCode}") public ResponseEntity<?> downloadFile(@PathVariable("fileCode") String fileCode) { FileDownloadUtil downloadUtil = new FileDownloadUtil(); Resource resource = null; try { resource = downloadUtil.getFileAsResource(fileCode); } catch (IOException e) { return ResponseEntity.internalServerError().build(); } if (resource == null) { return new ResponseEntity<>("File not found", HttpStatus.NOT_FOUND); } String contentType = "application/octet-stream"; String headerValue = "attachment; filename=\"" + resource.getFilename() + "\""; return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .header(HttpHeaders.CONTENT_DISPOSITION, headerValue) .body(resource); } }As you see, the handler method uses the FileDownloadUtil class to look for a matching file based on the given fileCode. If no file found, it returns HTTP status NOT FOUND (404). If a file found, it sends the file resource as body of the response.Also note the statements that set the content type and header of the response.
http://localhost:8080/downloadFile/mggiKcFQ
If you will see some special characters in the response’s body, which is the content of the file downloaded. You can click Save Response > Save to a file to store the file on disk:Those are some code examples about File upload API and File download API implemented in Java and Spring framework. You can get the sample project code from this GitHub repo.To see the coding in action, I recommend you watch my video below: