Spring boot builds a file server to solve the problem of uploading and downloading multiple pictures at the same time
In normal business scenarios, it is inevitable to build a file upload server as a public service. Generally, only a single file is uploaded. In the actual business scenario, it is found that uploading a single file does not meet some business needs. Therefore, we need to solve how to write an interface for uploading multiple files at the same time and return the downloadable file address;
No more nonsense. We won't build a spring boot project from scratch. If you don't know, please go directly to the official website to view the instance.
Let's take the above picture as an example. The example is relatively simple and for reference only:
1 back end upload picture interface logic
UploadController.java package com.zz.controllers.fileUpload; import com.zz.Application; import com.zz.model.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.Configuration; 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; import java.io.*; import java.net.Inet4Address; import java.net.InetAddress; import java.nio.file.Path; import java.util.ArrayList; import java.util.UUID; import static com.zz.config.ConfigConstants.getFileDir; @RestController @Configuration public class UploadController { private static final Logger log = LoggerFactory.getLogger(Application.class); @Value("${server.port}") private String port; //获取当前IP地址 public String getIp() { InetAddress localhost = null; try { localhost = Inet4Address.getLocalHost(); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } return localhost.getHostAddress(); } @PostMapping(value = "/upload",consumes = {"multipart/form-data"}) public Response upload(@RequestParam("file") multipartfile[] files,Response response) { log.info("上传多个文件"); StringBuilder builder = new StringBuilder(); // file address String fileAddress ="http://"+ getIp()+ ":" + port + File.separator; ArrayList<String> imgurls = new ArrayList<String>(); try { for (int i = 0; i < files.length; i++) { // old file name String fileName = files[i].getOriginalFilename(); // new filename String generateFileName = UUID.randomUUID().toString().replaceAll("-","") + fileName.substring(fileName.lastIndexOf(".")); // store filename String distFileAddress = fileAddress + generateFileName; builder.append(distFileAddress+","); imgurls.add(distFileAddress); // generate file to disk files[i].transferTo(new File(getFileDir() + generateFileName)); } } catch (Exception e) { e.printStackTrace(); } response.setMsg("success"); log.info(builder.toString()); response.setData(imgurls); return response; } }
Relative to the reception of a single file, we directly accept multiple file objects, and then traverse to generate each corresponding address.
Of which:
Getfiledir sets the address where the pictures are stored. I choose to store them elsewhere than the project
com.zz.config.ConfigConstants.getFileDir package com.zz.config; public class ConfigConstants { public static String fileDir; public static String getFileDir() { fileDir = "/Users/wz/projects/blog/uploadFile/"; return fileDir; } }
After we generate files to the specified folder, how can we configure the current server to access the static file and image resources outside the project and download them?
We will use the spring boot configuration file application YML, there are other methods, such as webmvcconfigurer, which will not be repeated here.
application.yml pring: jpa: show-sql: true hibernate: ddl-auto: update servlet: multipart: max-file-size: 10MB max-request-size: 10MB profiles: active: dev # 静态资源配置 mvc: static-path-pattern: /** resources: static-locations: file:/Users/wz/projects/blog/uploadFile/,classpath:/static/,classpath:/resources/,classpath:/file/,classpath:/templates/ server: use-forward-headers: true tomcat: remote-ip-header: X-Real-IP protocol-header: X-Forwarded-Proto #自定义 my: tokenURL: "55555" authURL: "88888"
After that, we are in the generated results http://192.168.31.77:8080/a7ef32e3922b46aea256a93dd53de288.png , such an address can substantially point the file to file: / users / WZ / projects / blog / UploadFile /, which is roughly a simple file server configuration. Of course, it is far less than this. There are compression functions, which will be discussed later.
The back-end logic is clear;
How can the front end send multiple file objects to the back end at the same time?
2. How to transfer parameters when uploading multiple files at the front end
html
<input type="file" multiple class="el-upload" accept="image/*" name="file">
js
//upload var uploadBtn = document.querySelector('.el-upload'); uploadBtn.onchange = function (e) { let files = this.files; console.log(this.files); const xhr = new XMLHttpRequest(); xhr.open("post","/upload",true); // xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { console.log(JSON.parse(this.responseText)); const {data} = JSON.parse(this.responseText); if(!data) return; const imageList = data.slice(0); let imageStr = ''; imageList.forEach(img=>{ imageStr += `<img src="${img}" />`; }); document.getElementById("result").innerHTML = imageStr; } }; const formData = new FormData(); // 多个file 同时上传 if(files && files.length){ for (let i=0;i<files.length;i++) { formData.append("file",files[i]) } } console.log(formData); xhr.send(formData); };
The front end sends a post request through formdata parameters;
Different from the previous single formdata append(); Here, we can append multiple binary file streams with the same name at the same time;
! [image-20191123234150228](assets/image-
. png)
As shown in the figure, when we deploy to the server, it can be used as a web server for everyone.