How To Upload A File Using Http Post In Java
Uploading and downloading files are very mutual tasks for which developers need to write code in their applications.
In this article, Yous'll learn how to upload and download files in a RESTful bound boot web service.
We'll first build the REST APIs for uploading and downloading files, and then test those APIs using Postman. We'll too write front-end lawmaking in javascript to upload files.
Following is the concluding version of our application -
All right! Permit'southward go started.
Creating the Application
Permit's generate our application using Spring Kicking CLI. Fire up your terminal, and blazon the following control to generate the app -
$ spring init --name=file-demo --dependencies=spider web file-demo Using service at https://start.bound.io Project extracted to '/Users/rajeevkumarsingh/spring-kicking/file-demo'
You may likewise generate the awarding through Leap Initializr web tool by post-obit the instructions below -
- Open http://get-go.spring.io
- Enter file-demo in the "Artifact" field.
- Enter com.example.filedemo in the "Package" field.
- Add Spider web in the "Dependencies" section.
- Click Generate to generate and download the projection.
That's it! You may now unzip the downloaded awarding annal and import it into your favorite IDE.
Configuring Server and File Storage Backdrop
Showtime thing First! Let'southward configure our Spring Boot awarding to enable Multipart file uploads, and define the maximum file size that tin be uploaded. We'll as well configure the directory into which all the uploaded files will be stored.
Open up src/main/resources/application.backdrop
file, and add the following properties to information technology -
## MULTIPART (MultipartProperties) # Enable multipart uploads jump.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 jump.servlet.multipart.max-request-size = 215MB ## File Storage Properties # All files uploaded through the Balance API will be stored in this directory file.upload-dir = /Users/callicoder/uploads
Note: Delight change the
file.upload-dir
property to the path where yous desire the uploaded files to be stored.
Automatically binding properties to a POJO class
Jump Boot has an awesome characteristic called @ConfigurationProperties
using which you tin automatically bind the properties defined in the awarding.properties
file to a POJO class.
Let's define a POJO class called FileStorageProperties
inside com.example.filedemo.holding
package to bind all the file storage properties -
package com.instance.filedemo.holding ; import org.springframework.boot.context.properties. ConfigurationProperties ; @ConfigurationProperties (prefix = "file" ) public class FileStorageProperties { individual String uploadDir; public String getUploadDir ( ) { render uploadDir; } public void setUploadDir ( String uploadDir) { this .uploadDir = uploadDir; } }
The @ConfigurationProperties(prefix = "file")
annotation does its job on application startup and binds all the properties with prefix file
to the corresponding fields of the POJO class.
If yous define additional file
backdrop in future, you lot may simply add a corresponding field in the above class, and spring kicking will automatically bind the field with the belongings value.
Enable Configuration Properties
Now, To enable the ConfigurationProperties
feature, you need to add @EnableConfigurationProperties
note to any configuration grade.
Open the primary grade src/main/coffee/com/example/filedemo/FileDemoApplication.java
, and add the @EnableConfigurationProperties
annotation to it like so -
package com.example.filedemo ; import com.example.filedemo.property. FileStorageProperties ; import org.springframework.boot. SpringApplication ; import org.springframework.boot.autoconfigure. SpringBootApplication ; import org.springframework.boot.context.properties. EnableConfigurationProperties ; @SpringBootApplication @EnableConfigurationProperties ( { FileStorageProperties . class } ) public form FileDemoApplication { public static void primary ( String [ ] args) { SpringApplication . run ( FileDemoApplication . class , args) ; } }
Writing APIs for File Upload and Download
Permit's at present write the Residue APIs for uploading and downloading files. Create a new controller form called FileController
within com.example.filedemo.controller
package.
Here is the complete lawmaking for FileController
-
bundle com.instance.filedemo.controller ; import com.case.filedemo.payload. UploadFileResponse ; import com.instance.filedemo.service. FileStorageService ; import org.slf4j. Logger ; import org.slf4j. LoggerFactory ; import org.springframework.beans.mill.note. 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.spider web.bind.annotation. * ; import org.springframework.web.multipart. MultipartFile ; import org.springframework.spider web.servlet.support. ServletUriComponentsBuilder ; import javax.servlet.http. HttpServletRequest ; import coffee.io. IOException ; import java.util. Arrays ; import coffee.util. Listing ; import java.util.stream. Collectors ; @RestController public grade 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 < Resources > downloadFile ( @PathVariable Cord fileName, HttpServletRequest request) { // Load file every bit Resources Resources resource = fileStorageService. loadFileAsResource (fileName) ; // Try to decide file's content type Cord contentType = cypher ; endeavor { contentType = asking. getServletContext ( ) . getMimeType (resources. getFile ( ) . getAbsolutePath ( ) ) ; } catch ( IOException ex) { logger. info ( "Could non determine file type." ) ; } // Fallback to the default content blazon if type could non be determined if (contentType == null ) { contentType = "application/octet-stream" ; } render ResponseEntity . ok ( ) . contentType ( MediaType . parseMediaType (contentType) ) . header ( HttpHeaders .CONTENT_DISPOSITION, "attachment; filename=\"" + resource. getFilename ( ) + "\"" ) . trunk (resource) ; } }
The FileController
grade uses FileStorageService
for storing files in the file system and retrieving them. It returns a payload of type UploadFileResponse
after the upload is completed. Allow's define these classes one by one.
UploadFileResponse
Equally the name suggests, this class is used to return the response from the /uploadFile
and /uploadMultipleFiles
APIs.
Create UploadFileResponse
class inside com.example.filedemo.payload
package with the following contents -
package com.example.filedemo.payload ; public class UploadFileResponse { individual Cord fileName; private Cord fileDownloadUri; private String fileType; individual 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 for Storing Files in the FileSystem and retrieving them
Let's now write the service for storing files in the file system and retrieving them. Create a new class called FileStorageService.coffee
inside com.case.filedemo.service
bundle with the following contents -
package com.case.filedemo.service ; import com.instance.filedemo.exception. FileStorageException ; import com.example.filedemo.exception. MyFileNotFoundException ; import com.example.filedemo.property. FileStorageProperties ; import org.springframework.beans.factory.annotation. Autowired ; import org.springframework.cadre.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.cyberspace. MalformedURLException ; import java.nio.file. Files ; import java.nio.file. Path ; import coffee.nio.file. Paths ; import java.nio.file. StandardCopyOption ; @Service public grade FileStorageService { private terminal Path fileStorageLocation; @Autowired public FileStorageService ( FileStorageProperties fileStorageProperties) { this .fileStorageLocation = Paths . go (fileStorageProperties. getUploadDir ( ) ) . toAbsolutePath ( ) . normalize ( ) ; try { Files . createDirectories ( this .fileStorageLocation) ; } catch ( Exception ex) { throw new FileStorageException ( "Could non create the directory where the uploaded files will be stored." , ex) ; } } public String storeFile ( MultipartFile file) { // Normalize file proper noun String fileName = StringUtils . cleanPath (file. getOriginalFilename ( ) ) ; try { // Check if the file's name contains invalid characters if (fileName. contains ( ".." ) ) { throw new FileStorageException ( "Lamentable! 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 . re-create (file. getInputStream ( ) , targetLocation, StandardCopyOption .REPLACE_EXISTING) ; return fileName; } catch ( IOException ex) { throw new FileStorageException ( "Could non store file " + fileName + ". Please endeavour again!" , ex) ; } } public Resource loadFileAsResource ( String fileName) { try { Path filePath = this .fileStorageLocation. resolve (fileName) . normalize ( ) ; Resource resources = new UrlResource (filePath. toUri ( ) ) ; if (resource. exists ( ) ) { return resource; } else { throw new MyFileNotFoundException ( "File not found " + fileName) ; } } take hold of ( MalformedURLException ex) { throw new MyFileNotFoundException ( "File not establish " + fileName, ex) ; } } }
Exception Classes
The FileStorageService
form throws some exceptions in case of unexpected situations. Following are the definitions of those exception classes (All the exception classes go inside the parcel com.example.filedemo.exception
).
1. FileStorageException
It's thrown when an unexpected situation occurs while storing a file in the file organization -
bundle com.example.filedemo.exception ; public form FileStorageException extends RuntimeException { public FileStorageException ( String message) { super (bulletin) ; } public FileStorageException ( String message, Throwable crusade) { super (bulletin, cause) ; } }
ii. MyFileNotFoundException
It's thrown when a file that the user is trying to download is not found.
packet com.case.filedemo.exception ; import org.springframework.http. HttpStatus ; import org.springframework.web.bind.annotation. ResponseStatus ; @ResponseStatus ( HttpStatus .NOT_FOUND) public grade MyFileNotFoundException extends RuntimeException { public MyFileNotFoundException ( Cord message) { super (message) ; } public MyFileNotFoundException ( String bulletin, Throwable cause) { super (message, cause) ; } }
Note that, nosotros've annotated the to a higher place exception form with @ResponseStatus(HttpStatus.NOT_FOUND)
. This ensures that Leap boot responds with a 404 Not Found
status when this exception is thrown.
Running the Application and Testing the APIs via Postman
We're washed developing our backend APIs. Let'south run the application and test the APIs via Postman. Type the following control from the root directory of the projection to run the application -
Once started, the application tin can be accessed at http://localhost:8080
.
ane. Upload File
2. Upload Multiple Files
iii. Download File
Developing the Front End
Our backend APIs are working fine. Let's now write the front end code to allow users upload and download files from our web app.
All the front end files volition get within src/principal/resources/static
folder. Following is the directory structure of our front-end lawmaking -
static └── css └── main.css └── js └── main.js └── index.html
A bit of HTML
<! DOCTYPE html > <html > <caput > <meta proper noun = "viewport" content = "width=device-width, initial-calibration=i.0, minimum-scale=1.0" > <title > Jump Boot File Upload / Download Rest API Example </title > <link rel = "stylesheet" href = "/css/principal.css" /> </head > <torso > <noscript > <h2 > Sorry! Your browser doesn't support Javascript </h2 > </noscript > <div class = "upload-container" > <div class = "upload-header" > <h2 > Spring Kick File Upload / Download Residue API Example </h2 > </div > <div course = "upload-content" > <div class = "unmarried-upload" > <h3 > Upload Single File </h3 > <course id = "singleUploadForm" proper noun = "singleUploadForm" > <input id = "singleFileUploadInput" type = "file" name = "file" class = "file-input" required /> <push button type = "submit" course = "chief submit-btn" > Submit </button > </class > <div class = "upload-response" > <div id = "singleFileUploadError" > </div > <div id = "singleFileUploadSuccess" > </div > </div > </div > <div class = "multiple-upload" > <h3 > Upload Multiple Files </h3 > <class id = "multipleUploadForm" name = "multipleUploadForm" > <input id = "multipleFileUploadInput" type = "file" proper noun = "files" form = "file-input" multiple required /> <button type = "submit" class = "primary 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 > </trunk > </html >
Some Javascript
'use strict' ; var singleUploadForm = document. querySelector ( '#singleUploadForm' ) ; var singleFileUploadInput = document. querySelector ( '#singleFileUploadInput' ) ; var singleFileUploadError = document. querySelector ( '#singleFileUploadError' ) ; var singleFileUploadSuccess = document. querySelector ( '#singleFileUploadSuccess' ) ; var multipleUploadForm = document. querySelector ( '#multipleUploadForm' ) ; var multipleFileUploadInput = document. querySelector ( '#multipleFileUploadInput' ) ; var multipleFileUploadError = document. querySelector ( '#multipleFileUploadError' ) ; var multipleFileUploadSuccess = document. querySelector ( '#multipleFileUploadSuccess' ) ; role uploadSingleFile ( file ) { var formData = new FormData ( ) ; formData. append ( "file" , file) ; var xhr = new XMLHttpRequest ( ) ; xhr. open ( "Postal service" , "/uploadFile" ) ; xhr. onload = function ( ) { panel. log (xhr.responseText) ; var response = JSON . parse (xhr.responseText) ; if (xhr.condition == 200 ) { singleFileUploadError.way.display = "none" ; singleFileUploadSuccess.innerHTML = "<p>File Uploaded Successfully.</p><p>DownloadUrl : <a href='" + response.fileDownloadUri + "' target='_blank'>" + response.fileDownloadUri + "</a></p>" ; singleFileUploadSuccess.way.brandish = "block" ; } else { singleFileUploadSuccess.style.display = "none" ; singleFileUploadError.innerHTML = (response && response.message) || "Some Fault Occurred" ; } } xhr. send (formData) ; } role uploadMultipleFiles ( files ) { var formData = new FormData ( ) ; for ( var index = 0 ; index < files.length; alphabetize++ ) { formData. suspend ( "files" , files[index] ) ; } var xhr = new XMLHttpRequest ( ) ; xhr. open ( "Mail service" , "/uploadMultipleFiles" ) ; xhr. onload = function ( ) { panel. log (xhr.responseText) ; var response = JSON . parse (xhr.responseText) ; if (xhr.status == 200 ) { multipleFileUploadError.style.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.fashion.display = "cake" ; } else { multipleFileUploadSuccess.style.display = "none" ; multipleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred" ; } } xhr. send (formData) ; } singleUploadForm. addEventListener ( 'submit' , function ( event ) { var files = singleFileUploadInput.files; if (files.length === 0 ) { singleFileUploadError.innerHTML = "Please select a file" ; singleFileUploadError.style.display = "block" ; } uploadSingleFile (files[ 0 ] ) ; issue. preventDefault ( ) ; } , true ) ; multipleUploadForm. addEventListener ( 'submit' , function ( outcome ) { var files = multipleFileUploadInput.files; if (files.length === 0 ) { multipleFileUploadError.innerHTML = "Please select at to the lowest degree one file" ; multipleFileUploadError.style.display = "block" ; } uploadMultipleFiles (files) ; result. preventDefault ( ) ; } , true ) ;
The above code is self explanatory. I'chiliad using XMLHttpRequest
along with FormData
object to upload file(due south) as multipart/course-data
.
And some CSS
* { -webkit-box-sizing : border-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-height : 1.58; color : #333; background-color : #f4f4f4; } body:earlier { summit : 50%; width : 100%; position : accented; acme : 0; left : 0; background : #128ff2; content : "" ; z-alphabetize : 0; } .clearfix:after { display : block; content : "" ; clear : both; } h1, h2, h3, h4, h5, h6 { margin-elevation : 20px; margin-bottom : 20px; } h1 { font-size : 1.7em; } a { colour : #128ff2; } button { box-shadow : none; border : 1px solid transparent; font-size : 14px; outline : none; line-height : 100%; white-space : nowrap; vertical-marshal : middle; 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[type="file"] { border : 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-height : 0; margin-left : 10px; } } .upload-container { max-width : 700px; margin-left : motorcar; margin-correct : auto; background-colour : #fff; box-shadow : 0 1px 11px rgba (0, 0, 0, 0.27) ; margin-top : 60px; min-height : 400px; position : relative; padding : 20px; } .upload-header { border-bottom : 1px solid #ececec; } .upload-header h2 { font-weight : 500; } .single-upload { padding-bottom : 20px; margin-lesser : 20px; border-bottom : 1px solid #e8e8e8; } .upload-response { overflow-10 : hidden; word-pause : pause-all; }
If you utilise JQuery
If you prefer using jQuery instead of vanilla javascript, then you tin can upload files using jQuery.ajax()
method similar so -
$ ( '#singleUploadForm' ) . submit ( function ( event ) { var formElement = this ; // You can straight create form information from the form element // (Or you could get the files from input element and append them to FormData every bit nosotros did in vanilla javascript) var formData = new FormData (formElement) ; $. ajax ( { type: "Post" , enctype: 'multipart/form-data' , url: "/uploadFile" , data: formData, processData: false , contentType: false , success : function ( response ) { console. log (response) ; // process response } , fault : function ( error ) { console. log (error) ; // procedure error } } ) ; result. preventDefault ( ) ; } ) ;
Conclusion
All right folks! In this commodity, we learned how to upload single besides equally multiple files via Residuum APIs written in Leap Boot. We also learned how to download files in Spring Kick. Finally, nosotros wrote code to upload files by calling the APIs through javascript.
I hope the mail service was helpful to you. You tin download the entire code for the projection that nosotros built in this commodity from the github repository.
If y'all want to store files in MySQL database instead of the local file system, then check out the following article -
Jump Boot File Upload / Download with JPA, Hibernate, and MySQL database
Thank you for reading! Run across you in the side by side mail!
Source: https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/
Posted by: renoofuld1952.blogspot.com
0 Response to "How To Upload A File Using Http Post In Java"
Post a Comment