Where Does Upload File Uploaded to Spring
Uploading and downloading files are very common tasks for which developers need to write lawmaking in their applications.
In this article, Yous'll learn how to upload and download files in a RESTful jump kick web service.
We'll first build the Rest APIs for uploading and downloading files, and then examination those APIs using Postman. We'll as well write front-terminate lawmaking in javascript to upload files.
Following is the final version of our application -
All right! Permit's get started.
Creating the Application
Let'southward generate our application using Spring Boot CLI. Fire upwardly your terminal, and blazon the post-obit control to generate the app -
$ bound init --name=file-demo --dependencies=spider web file-demo Using service at https://start.spring.io Project extracted to '/Users/rajeevkumarsingh/spring-kicking/file-demo' Y'all may besides generate the application through Spring Initializr spider web tool by following the instructions below -
- Open http://showtime.spring.io
- Enter file-demo in the "Artifact" field.
- Enter com.example.filedemo in the "Package" field.
- Add Web in the "Dependencies" section.
- Click Generate to generate and download the project.
That'due south information technology! You may now unzip the downloaded application archive and import information technology into your favorite IDE.
Configuring Server and File Storage Properties
Outset matter First! Permit's configure our Bound Boot awarding to enable Multipart file uploads, and define the maximum file size that can be uploaded. We'll also configure the directory into which all the uploaded files will be stored.
Open src/main/resources/application.properties file, and add together the following properties to it -
## MULTIPART (MultipartProperties) # Enable multipart uploads bound.servlet.multipart.enabled = truthful # Threshold after which files are written to disk. bound.servlet.multipart.file-size-threshold = 2KB # Max file size. spring.servlet.multipart.max-file-size = 200MB # Max Request Size jump.servlet.multipart.max-request-size = 215MB ## File Storage Properties # All files uploaded through the Rest API volition exist stored in this directory file.upload-dir = /Users/callicoder/uploads Note: Please change the
file.upload-dirproperty to the path where you want the uploaded files to be stored.
Automatically binding backdrop to a POJO grade
Spring Boot has an crawly characteristic called @ConfigurationProperties using which you tin automatically bind the properties divers in the application.properties file to a POJO form.
Let's define a POJO course called FileStorageProperties inside com.instance.filedemo.belongings package to bind all the file storage backdrop -
package com.example.filedemo.property ; import org.springframework.boot.context.properties. ConfigurationProperties ; @ConfigurationProperties (prefix = "file" ) public class FileStorageProperties { private Cord uploadDir; public String getUploadDir ( ) { return uploadDir; } public void setUploadDir ( String uploadDir) { this .uploadDir = uploadDir; } } The @ConfigurationProperties(prefix = "file") annotation does its job on application startup and binds all the backdrop with prefix file to the corresponding fields of the POJO course.
If you ascertain boosted file properties in future, you lot may simply add a corresponding field in the above class, and spring kick will automatically bind the field with the holding value.
Enable Configuration Properties
Now, To enable the ConfigurationProperties characteristic, you need to add @EnableConfigurationProperties annotation to any configuration grade.
Open up the main class src/main/java/com/example/filedemo/FileDemoApplication.coffee, and add the @EnableConfigurationProperties annotation to information technology like and so -
package com.example.filedemo ; import com.example.filedemo.belongings. FileStorageProperties ; import org.springframework.kick. SpringApplication ; import org.springframework.boot.autoconfigure. SpringBootApplication ; import org.springframework.kick.context.properties. EnableConfigurationProperties ; @SpringBootApplication @EnableConfigurationProperties ( { FileStorageProperties . form } ) public class FileDemoApplication { public static void main ( Cord [ ] args) { SpringApplication . run ( FileDemoApplication . grade , args) ; } } Writing APIs for File Upload and Download
Let'southward now write the REST APIs for uploading and downloading files. Create a new controller class called FileController inside com.example.filedemo.controller package.
Hither is the complete code for FileController -
parcel com.instance.filedemo.controller ; import com.case.filedemo.payload. UploadFileResponse ; import com.example.filedemo.service. FileStorageService ; import org.slf4j. Logger ; import org.slf4j. LoggerFactory ; import org.springframework.beans.factory.annotation. Autowired ; import org.springframework.cadre.io. Resource ; import org.springframework.http. HttpHeaders ; import org.springframework.http. MediaType ; import org.springframework.http. ResponseEntity ; import org.springframework.web.bind.annotation. * ; import org.springframework.web.multipart. MultipartFile ; import org.springframework.web.servlet.support. ServletUriComponentsBuilder ; import javax.servlet.http. HttpServletRequest ; import java.io. IOException ; import java.util. Arrays ; import java.util. List ; import java.util.stream. Collectors ; @RestController public class FileController { individual static last 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 Resources resources = fileStorageService. loadFileAsResource (fileName) ; // Endeavour to make up one's mind file'southward content type String contentType = cypher ; try { contentType = request. getServletContext ( ) . getMimeType (resource. getFile ( ) . getAbsolutePath ( ) ) ; } catch ( IOException ex) { logger. info ( "Could not determine file type." ) ; } // Fallback to the default content blazon if type could not be determined if (contentType == null ) { contentType = "awarding/octet-stream" ; } return ResponseEntity . ok ( ) . contentType ( MediaType . parseMediaType (contentType) ) . header ( HttpHeaders .CONTENT_DISPOSITION, "zipper; filename=\"" + resources. getFilename ( ) + "\"" ) . body (resource) ; } } The FileController class uses FileStorageService for storing files in the file system and retrieving them. It returns a payload of type UploadFileResponse after the upload is completed. Let'south ascertain these classes one by 1.
UploadFileResponse
As the name suggests, this class is used to render the response from the /uploadFile and /uploadMultipleFiles APIs.
Create UploadFileResponse grade inside com.instance.filedemo.payload packet with the post-obit contents -
packet com.case.filedemo.payload ; public grade UploadFileResponse { private String fileName; private String fileDownloadUri; individual String fileType; individual long size; public UploadFileResponse ( String fileName, Cord fileDownloadUri, String fileType, long size) { this .fileName = fileName; this .fileDownloadUri = fileDownloadUri; this .fileType = fileType; this .size = size; } // Getters and Setters (Omitted for brevity) } Service for Storing Files in the FileSystem and retrieving them
Allow's now write the service for storing files in the file system and retrieving them. Create a new class chosen FileStorageService.java inside com.example.filedemo.service parcel with the post-obit contents -
packet com.instance.filedemo.service ; import com.example.filedemo.exception. FileStorageException ; import com.example.filedemo.exception. MyFileNotFoundException ; import com.example.filedemo.property. FileStorageProperties ; import org.springframework.beans.factory.note. Autowired ; import org.springframework.core.io. Resource ; import org.springframework.core.io. UrlResource ; import org.springframework.stereotype. Service ; import org.springframework.util. StringUtils ; import org.springframework.web.multipart. MultipartFile ; import java.io. IOException ; import java.net. MalformedURLException ; import java.nio.file. Files ; import java.nio.file. Path ; import coffee.nio.file. Paths ; import java.nio.file. StandardCopyOption ; @Service public class FileStorageService { private final Path fileStorageLocation; @Autowired public FileStorageService ( FileStorageProperties fileStorageProperties) { this .fileStorageLocation = Paths . become (fileStorageProperties. getUploadDir ( ) ) . toAbsolutePath ( ) . normalize ( ) ; effort { Files . createDirectories ( this .fileStorageLocation) ; } catch ( Exception ex) { throw new FileStorageException ( "Could non create the directory where the uploaded files volition be stored." , ex) ; } } public String storeFile ( MultipartFile file) { // Normalize file name String fileName = StringUtils . cleanPath (file. getOriginalFilename ( ) ) ; attempt { // Check if the file'south proper noun contains invalid characters if (fileName. contains ( ".." ) ) { throw new FileStorageException ( "Sorry! Filename contains invalid path sequence " + fileName) ; } // Re-create 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; } take hold of ( IOException ex) { throw new FileStorageException ( "Could non store file " + fileName + ". Please try again!" , ex) ; } } public Resource loadFileAsResource ( String fileName) { try { Path filePath = this .fileStorageLocation. resolve (fileName) . normalize ( ) ; Resources resources = new UrlResource (filePath. toUri ( ) ) ; if (resources. exists ( ) ) { return resource; } else { throw new MyFileNotFoundException ( "File not constitute " + fileName) ; } } catch ( MalformedURLException ex) { throw new MyFileNotFoundException ( "File non plant " + fileName, ex) ; } } } Exception Classes
The FileStorageService grade throws some exceptions in case of unexpected situations. Post-obit are the definitions of those exception classes (All the exception classes go inside the package com.instance.filedemo.exception).
one. FileStorageException
It's thrown when an unexpected situation occurs while storing a file in the file system -
package com.case.filedemo.exception ; public class FileStorageException extends RuntimeException { public FileStorageException ( String message) { super (message) ; } public FileStorageException ( String message, Throwable cause) { super (bulletin, cause) ; } } 2. MyFileNotFoundException
Information technology's thrown when a file that the user is trying to download is not found.
parcel com.example.filedemo.exception ; import org.springframework.http. HttpStatus ; import org.springframework.spider web.demark.note. ResponseStatus ; @ResponseStatus ( HttpStatus .NOT_FOUND) public class MyFileNotFoundException extends RuntimeException { public MyFileNotFoundException ( String message) { super (message) ; } public MyFileNotFoundException ( String message, Throwable crusade) { super (bulletin, cause) ; } } Notation that, nosotros've annotated the above exception class with @ResponseStatus(HttpStatus.NOT_FOUND). This ensures that Spring kicking responds with a 404 Not Found condition when this exception is thrown.
Running the Application and Testing the APIs via Postman
We're done developing our backend APIs. Let's run the application and exam the APIs via Postman. Type the following control from the root directory of the projection to run the application -
Once started, the application can be accessed at http://localhost:8080.
1. Upload File
2. Upload Multiple Files
3. Download File
Developing the Forepart
Our backend APIs are working fine. Allow's at present write the forepart end lawmaking to let users upload and download files from our web app.
All the front end stop files volition go inside src/main/resources/static binder. Following is the directory structure of our front-end code -
static └── css └── main.css └── js └── main.js └── index.html A bit of HTML
<! DOCTYPE html > <html > <head > <meta name = "viewport" content = "width=device-width, initial-scale=1.0, minimum-calibration=1.0" > <title > Spring Kick File Upload / Download Rest API Example </title > <link rel = "stylesheet" href = "/css/main.css" /> </caput > <torso > <noscript > <h2 > Sorry! Your browser doesn't support Javascript </h2 > </noscript > <div course = "upload-container" > <div grade = "upload-header" > <h2 > Spring Kicking File Upload / Download Rest API Case </h2 > </div > <div class = "upload-content" > <div class = "single-upload" > <h3 > Upload Single File </h3 > <form id = "singleUploadForm" proper noun = "singleUploadForm" > <input id = "singleFileUploadInput" type = "file" name = "file" class = "file-input" required /> <button type = "submit" grade = "primary submit-btn" > Submit </button > </grade > <div form = "upload-response" > <div id = "singleFileUploadError" > </div > <div id = "singleFileUploadSuccess" > </div > </div > </div > <div grade = "multiple-upload" > <h3 > Upload Multiple Files </h3 > <form id = "multipleUploadForm" name = "multipleUploadForm" > <input id = "multipleFileUploadInput" blazon = "file" proper noun = "files" form = "file-input" multiple required /> <button type = "submit" course = "master submit-btn" > Submit </button > </form > <div class = "upload-response" > <div id = "multipleFileUploadError" > </div > <div id = "multipleFileUploadSuccess" > </div > </div > </div > </div > </div > <script src = "/js/main.js" > </script > </body > </html > Some Javascript
'use strict' ; var singleUploadForm = document. querySelector ( '#singleUploadForm' ) ; var singleFileUploadInput = certificate. querySelector ( '#singleFileUploadInput' ) ; var singleFileUploadError = document. querySelector ( '#singleFileUploadError' ) ; var singleFileUploadSuccess = document. querySelector ( '#singleFileUploadSuccess' ) ; var multipleUploadForm = document. querySelector ( '#multipleUploadForm' ) ; var multipleFileUploadInput = certificate. querySelector ( '#multipleFileUploadInput' ) ; var multipleFileUploadError = document. querySelector ( '#multipleFileUploadError' ) ; var multipleFileUploadSuccess = document. querySelector ( '#multipleFileUploadSuccess' ) ; function uploadSingleFile ( file ) { var formData = new FormData ( ) ; formData. append ( "file" , file) ; var xhr = new XMLHttpRequest ( ) ; xhr. open ( "Post" , "/uploadFile" ) ; xhr. onload = function ( ) { console. log (xhr.responseText) ; var response = JSON . parse (xhr.responseText) ; if (xhr.status == 200 ) { singleFileUploadError.mode.brandish = "none" ; singleFileUploadSuccess.innerHTML = "<p>File Uploaded Successfully.</p><p>DownloadUrl : <a href='" + response.fileDownloadUri + "' target='_blank'>" + response.fileDownloadUri + "</a></p>" ; singleFileUploadSuccess.style.display = "block" ; } else { singleFileUploadSuccess.way.display = "none" ; singleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred" ; } } xhr. transport (formData) ; } role uploadMultipleFiles ( files ) { var formData = new FormData ( ) ; for ( var index = 0 ; alphabetize < files.length; index++ ) { formData. append ( "files" , files[index] ) ; } var xhr = new XMLHttpRequest ( ) ; xhr. open up ( "Mail" , "/uploadMultipleFiles" ) ; xhr. onload = function ( ) { console. log (xhr.responseText) ; var response = JSON . parse (xhr.responseText) ; if (xhr.status == 200 ) { multipleFileUploadError.way.display = "none" ; var content = "<p>All Files Uploaded Successfully</p>" ; for ( var i = 0 ; i < response.length; i++ ) { content += "<p>DownloadUrl : <a href='" + response[i] .fileDownloadUri + "' target='_blank'>" + response[i] .fileDownloadUri + "</a></p>" ; } multipleFileUploadSuccess.innerHTML = content; multipleFileUploadSuccess.style.brandish = "cake" ; } else { multipleFileUploadSuccess.style.display = "none" ; multipleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred" ; } } xhr. send (formData) ; } singleUploadForm. addEventListener ( 'submit' , office ( outcome ) { var files = singleFileUploadInput.files; if (files.length === 0 ) { singleFileUploadError.innerHTML = "Please select a file" ; singleFileUploadError.fashion.display = "cake" ; } uploadSingleFile (files[ 0 ] ) ; event. preventDefault ( ) ; } , truthful ) ; multipleUploadForm. addEventListener ( 'submit' , function ( outcome ) { var files = multipleFileUploadInput.files; if (files.length === 0 ) { multipleFileUploadError.innerHTML = "Please select at least ane file" ; multipleFileUploadError.style.brandish = "cake" ; } uploadMultipleFiles (files) ; event. preventDefault ( ) ; } , true ) ; The above lawmaking is self explanatory. I'm using XMLHttpRequest along with FormData object to upload file(s) as multipart/form-data.
And some CSS
* { -webkit-box-sizing : edge-box; -moz-box-sizing : border-box; box-sizing : border-box; } body { margin : 0; padding : 0; font-weight : 400; font-family : "Helvetica Neue" , Helvetica, Arial, sans-serif; font-size : 1rem; line-top : i.58; color : #333; background-color : #f4f4f4; } body:before { pinnacle : 50%; width : 100%; position : absolute; top : 0; left : 0; background : #128ff2; content : "" ; z-alphabetize : 0; } .clearfix:later on { brandish : block; content : "" ; articulate : both; } h1, h2, h3, h4, h5, h6 { margin-meridian : 20px; margin-bottom : 20px; } h1 { font-size : i.7em; } a { color : #128ff2; } button { box-shadow : none; border : 1px solid transparent; font-size : 14px; outline : none; line-height : 100%; white-space : nowrap; vertical-align : eye; padding : 0.6rem 1rem; border-radius : 2px; transition : all 0.2s ease-in-out; cursor : pointer; min-height : 38px; } button.primary { background-color : #128ff2; box-shadow : 0 2px 2px 0 rgba (0, 0, 0, 0.12) ; color : #fff; } input { font-size : 1rem; } input[blazon="file"] { edge : 1px solid #128ff2; padding : 6px; max-width : 100%; } .file-input { width : 100%; } .submit-btn { display : block; margin-top : 15px; min-width : 100px; } @media screen and ( min-width : 500px) { .file-input { width : calc (100% - 115px) ; } .submit-btn { display : inline-block; margin-tiptop : 0; margin-left : 10px; } } .upload-container { max-width : 700px; margin-left : automobile; margin-right : car; groundwork-color : #fff; box-shadow : 0 1px 11px rgba (0, 0, 0, 0.27) ; margin-top : 60px; min-tiptop : 400px; position : relative; padding : 20px; } .upload-header { edge-bottom : 1px solid #ececec; } .upload-header h2 { font-weight : 500; } .single-upload { padding-bottom : 20px; margin-bottom : 20px; border-bottom : 1px solid #e8e8e8; } .upload-response { overflow-x : hidden; word-break : break-all; } If you use JQuery
If y'all prefer using jQuery instead of vanilla javascript, and so yous can upload files using jQuery.ajax() method like so -
$ ( '#singleUploadForm' ) . submit ( function ( upshot ) { var formElement = this ; // Yous tin can direct create grade data from the form element // (Or y'all could go the files from input element and append them to FormData equally we did in vanilla javascript) var formData = new FormData (formElement) ; $. ajax ( { type: "POST" , enctype: 'multipart/form-information' , url: "/uploadFile" , data: formData, processData: false , contentType: simulated , success : function ( response ) { console. log (response) ; // process response } , fault : office ( mistake ) { console. log (error) ; // process fault } } ) ; event. preventDefault ( ) ; } ) ; Conclusion
All right folks! In this article, nosotros learned how to upload single also equally multiple files via REST APIs written in Leap Boot. We as well learned how to download files in Leap Boot. Finally, we wrote code to upload files by calling the APIs through javascript.
I hope the post was helpful to you. You tin can download the entire lawmaking for the project that we built in this article from the github repository.
If you want to store files in MySQL database instead of the local file system, and so cheque out the post-obit article -
Spring Boot File Upload / Download with JPA, Hibernate, and MySQL database
Cheers for reading! Run across you in the next mail!
Source: https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/
0 Response to "Where Does Upload File Uploaded to Spring"
Postar um comentário