Files are passed between the front end and back end services in form-data form via POST requests.
By setting the Content-Type of the HTTP request response, the back end passes the data to the front end as a binary stream.
1 Use form-data to send data to the backend
1.1 Definition of back-end Data Receiving Interface
Back-end interface /form-data definition
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class FileTransmit {
@PostMapping(value = "/form-data")
public String formData(HttpServletRequest request,
@RequestParam(value = "email", required = false) String email,
@RequestParam(value = "file_excel", required = false) MultipartFile multipartFile,
UserInfo userInfo) {
StandardMultipartHttpServletRequest standardMultipartRequest = (StandardMultipartHttpServletRequest) request;
log.info("multipartFile in @RequestParam={}", multipartFile.getOriginalFilename());
MultiValueMap<String, MultipartFile> multiFileMap = standardMultipartRequest.getMultiFileMap();
for (String paramKey : multiFileMap.keySet()) {
List<MultipartFile> multipartFileList = multiFileMap.get(paramKey);
log.info("MultipartFile key={}, size={}", paramKey, multipartFileList.size());
for (MultipartFile curMultipartFile : multipartFileList) {
log.info("MultipartFile key={}, file name={}",
paramKey, curMultipartFile.getOriginalFilename());
log.info("MultipartFile in request equals to file in @RequestParam={}",
multipartFile.equals(curMultipartFile));
}
}
log.info("email in @RequestParam={}", email);
log.info("userInfo in RequestParam={}", userInfo);
Map<String, String[]> paramMap = standardMultipartRequest.getParameterMap();
for (String paramKey : paramMap.keySet()) {
log.info("param key={}, size={}, value={}",
paramKey, paramMap.get(paramKey).length, paramMap.get(paramKey));
}
return "Form Data processed finished!";
}
}
Copy the code
1.2 Postman Debugging Interface
Set request body to form-data, can pass text data and file data at the same time, file key can contain multiple files (file_excel), key can also duplicate (ID, name, email).
As a result, the @requestParam annotation fetches the data specified in the form-data key, while the HttpServletRequest Request contains all the form-data data.
Since @requestParam modifies email and multipartFile not as arrays or lists, text email takes a concatenated value, while file multipartFile takes the first value. To receive multiple files, change the interface definition to List
MultipartFile.
1.3 Front-end transmission of form-data
Fill in the data on the page with a simple HTML demonstration, and when you click submit, invoke the interface defined in Section 1.1 and pass the data to the back end as form-data.
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Upload FormData</title> </head> <body> <form id="Form1" action="http://localhost:8080/rest/form-data" method="post" enctype="multipart/form-data"> <div style="text-align: left"> ID: <input name="id" type="text" /> <br /> ID: <input name="id" type="text" /> <br /> Name: <input name="name" type="text" /> <br /> Name: <input name="name" type="text" /> <br /> Email: <input name="email" type="text" /> <br /> Email: <input name="email" type="text" /> <br /> File: <input id="1" name="file_excel" type="file" multiple="multiple" /> <br /> File: <input id="2" name="file_img" type="file" /> <br /> <input type="submit" value="submit" /> <input type="reset" value="reset" /> </div> </form> </body> </html>Copy the code
1.4 Back-end transmission of form-data
Shows how the backend directly encapsulates data in form-data format and then invokes the interface defined in Section 1.1 to implement file data transfer between back-end services.
HttpHeaders sets the data type passed by the request to form-data, encapsulates the Requset header and Request Body with HttpEntity, and calls the POST interface with the postForObject method of RestTemplate.
MultiValueMap is used to encapsulate data in form-data format, and FileSystemResource is used for file type data.
public class FileTransmitTest { private RestTemplate restTemplate; private final String URL_ROOT = "http://localhost:8080/rest"; @Before public void init() { restTemplate = new RestTemplate(); } @Test public void FormDataTest() { MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap(); requestBody.add("file_excel", new FileSystemResource(new File("E:\dataJava\data\city_info.xlsx"))); requestBody.add("file_excel", new FileSystemResource(new File("E:\dataJava\data\user_info.xlsx"))); requestBody.add("file_img", new FileSystemResource(new File("E:\dataJava\data\github.png"))); requestBody.add("email", "[email protected]"); requestBody.add("email", "[email protected]"); requestBody.add("id", "123"); requestBody.add("id", "12345"); requestBody.add("name", "zhangsan"); requestBody.add("name", "kuangtu"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(requestBody, httpHeaders); String response = restTemplate.postForObject(URL_ROOT+"/form-data", requestEntity, String.class); System.out.println(response); }}Copy the code
1.5 Send a file to the back end
Demonstrates that the back end receives a single file and saves it to the specified directory.
The interface definition
@ResponseBody @PostMapping(value = "/receive/single") public String receiveSingle(MultipartFile multipartFile) throws IOException { if (multipartFile == null) { return "received file is null!" ; } the info (" file the content-type = {} ", multipartFile. GetContentType ()); Log.info (" file size ={}", multipartfile.getsize ()); Log.info (" filename ={}", multipartfile.getName ()); The log. The info (" file original name = {} ", multipartFile. GetOriginalFilename ()); / / save the received File to the local File destFile = new File (at "E: \ \" + multipartFile getOriginalFilename ()); multipartFile.transferTo(destFile); return "Form Data processed finished!" ; }Copy the code
Interface call
Because the @requestParam annotation is not used in the interface definition, the variable multipartFile cannot be initialized if the key of the form-data parameter is not multipartFile. Only when the key of form-data is set to multipartFile, it can be initialized normally.
If the interface is defined as
public String receiveSingle(@RequestParam(value = "file") MultipartFile multipartFile) throws IOException
Copy the code
The key of form-data must be set to file to initialize multipartFile. Therefore, it is recommended that the value in @requestParam be the same as the variable name, and that the variable name be used for the key encapsulating the parameter when the interface calls.
1.6 summarize
- In order to
form-data
Data transfer to the back endrequest header
In thecontent-type="multipart/form-data"
. form-data
You can pass both text and files to the back end.- For the file type
form-data
Data, back-end interface toMultiPartFile
Type to receive and can passMultiPartFile
thetransferTo
Save the file locally. - For text type
form-data
Data, which can be received by defined classes or by primitive type variables. Spring
Project back-end interfaceHttpServletRequest request
All of themform-data
The data.
2 The back-end end transfers files to the front-end end
Here, as an example, the backend transmits pictures to the front-end, including the following three methods:
- The back end saves the image on the file storage server and returns the URL of the image to the front end. The front end sets SRC = URL of the IMG tag. This way should be the mainstream, but do not want to make a storage server, did not use this way.
- The back end returns the base64 encoding of the picture to the front end in the form of a string, and the front end then parses it into a picture display. This way although there is a large picture may be truncated Ken, but it is convenient to choose this way.
- The back end returns the binary stream of images as a byte array to the front end, which then parses it into a picture display. Returning binary streams is not only useful for images, but also for audio and video.
2.1 Base64 encoded transmission
Back-end interface definition
@crossorigin // Allow cross-domain access @getMapping (value = "/get-img-code") public String getImageBase64(String imageName) throws IOException { log.info("request param={}", imageName); String imgRootPath = "E:\dataJava\data\"; File imgFile = new File(imgRootPath + imageName + ".png"); InputStream inStream =new FileInputStream(imgFile); byte[] imgBytes = new byte[(int) imgFile.length()]; // Create an array of appropriate file sizes instream.read (imgBytes); // Read the contents of the file into the b[] array instream.close (); log.info("image size={}", imgBytes.length); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encodeBuffer(imgBytes); }Copy the code
2.2 Binary stream Transmission
Back-end interface definition
@crossorigin // Allow cross-domain access @getMapping (value = "/get-img-byte") public void getImageByte(HttpServletRequest Request, HttpServletResponse response, String imageName) throws IOException { String imgRootPath = "E:\dataJava\data\"; File imgFile = new File(imgRootPath + imageName + ".png"); InputStream inStream =new FileInputStream(imgFile); byte imgBytes[] = new byte[(int) imgFile.length()]; // Create an array of appropriate file sizes instream.read (imgBytes); // Read the contents of the file into the b[] array instream.close (); response.setContentType("application/octet-stream; charSet=UTF-8"); response.setContentLength(imgBytes.length); try (InputStream inputStream = new ByteArrayInputStream(imgBytes); OutputStream outputStream = response.getOutputStream()) { IOUtils.copy(inputStream, outputStream); outputStream.flush(); }catch (IOException e) { log.error("{}", e.getMessage()); }}Copy the code
2.3 HTML receive and display
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script SRC = "https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js" > < / script > < / head > < body > < div id = "main" style = "width: 100%; " > <div id="left" style="width:50%; float:left;" <p>< p>< p>< img id="base64_img" </p> <p>< p>< img id="base64_img" </p> src="" alt="" width="" height=""> </div> <div id="right" style="width:50%; float:left;" > <p>byte image</p> <img id="byte_img" src="http://localhost:8080/rest/get-img-byte? imageName=github" alt="" width="70%" height="70%"> </div> </div> <script> function getImgBase64() { $.ajax({ url : "http://localhost:8080/rest/get-img-code? ImageName =github", type: 'GET', contentType: false, Function (result) {console.log("reponse result:", result); var src = 'data:image/png; base64,' + result; $("#base64_img").attr('src', src); $("#base64_img").css("width", "70%"); $("#base64_img").css("height", "70%"); }, error : function(result) { console.log("reponse result:", result); alert("Post Faile!" ); }}); } </script> </body> </html>Copy the code
Operation effect:
Add: HTTP Headers
HTTP headers allow clients and servers to pass additional information through request and response. A request header consists of a name (case insensitive) followed by a colon (:) followed by a specific value (without a newline character).
Depending on the context, the header can be divided into:
- General Headers: A header that applies to both request and response messages, but has nothing to do with the data being transferred in the final message body.
- Request Headers: A header that contains more information about the resource to be fetched or about the client itself.
- Response Headers: A header that contains supplementary information about the Response, such as its location or the server itself (name and version, etc.).
- Entity Headers: Contains more information about the Entity body, such as the content-Length degree of the body or its MIME type.
In the Request headers
- Accept: Indicates that the browser tells the server the type of data that the browser can Accept.
- Accept-encoding: Indicates the Encoding method that the browser tells the server that the browser can receive the data.
- Accept-language: indicates the data Language that the browser tells the server that the browser can receive. It is usually used for internationalization.
- Content-type: indicates the file Type of the POST and PUT request body.
In the Reponse headers
- Content-type: indicates the data Type returned by the interface.
- Content-length: The Length of the body returned in octets (8-bit bytes)
References:
HTTP Headers
List of HTTP header fields