springboot2.3文件上传以及需要注意的事项

 

 

pom.xml中需要有指定springboot的版本

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.5.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
        <dependency>
		    <groupId>commons-io</groupId>
		    <artifactId>commons-io</artifactId>
		    <version>2.8.0</version>
		</dependency>

使用了springboot自带的文件上传,没有使用commons-fileupload,所以这里不引入,引入commons-io是使用IOUtils工具类。

        <dependency>
		    <groupId>commons-fileupload</groupId>
		    <artifactId>commons-fileupload</artifactId>
		    <version>1.4</version>
		</dependency>

 

application.properties

#springboot2.X开启文件上传与大小限制
spring.servlet.multipart.enabled=true
#表示上传的单个文件的最大大小,默认为 1MB
spring.servlet.multipart.max-file-size=1024MB
#表示多文件上传时文件的总大小,默认为 10MB
spring.servlet.multipart.max-request-size=1024MB
#表示文件写入磁盘的阀值,默认为 0
spring.servlet.multipart.file-size-threshold=0
#表示上传文件的临时保存位置
#spring.servlet.multipart.location=E:\\test\\temp
#表示文件是否延迟解析,默认为 false
spring.servlet.multipart.resolve-lazily=false

 

一、上传页面

thymeleaf的单文件上传页面:signleupload.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>SpringBoot 单文件上传页面</title>
</head>
<body>
<form method="post" action="/fileupload/signleupload" enctype="multipart/form-data">
文件:<input type="file" name="file"><br>
姓名:<input type="text" name="name"/><br>
<input type="submit" value="上传"><br>
</form>
</body>
</html>

thymeleaf的多文件上传页面:mutliupload.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>SpringBoot 多文件上传页面</title>
</head>
<body>
<form method="post" action="/fileupload/mutliupload" enctype="multipart/form-data">
文件1:<input type="file" name="file"><br>
文件2:<input type="file" name="file"><br>
文件3:<input type="file" name="file"><br>
<input type="submit" value="上传"><br>
</form>
</body>
</html>

 

2、文件上传控制器

FileUploadController.java

package com.imddysc.monitor.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.time.LocalDate;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/fileupload")
public class FileUploadController {
	
	private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);
	
	@Value("${upload.rootdir}")
	private String uploaddir;
    // /opt/upload
	
	@RequestMapping("/signleupload")
	public String signleUpload(HttpServletRequest request, @RequestParam("file") MultipartFile file) {
				
		String result = "";
		// 判断文件是否为空  
        if (!file.isEmpty()) {
            try {
                // 文件保存路径 
            	String filePath = uploaddir + "/"+ LocalDate.now().toString() +"/"+ file.getOriginalFilename();
            	logger.info("filePath: " + filePath);
            	File localFile = new File(filePath);
            	if(!localFile.getParentFile().exists()) {
            		localFile.getParentFile().mkdirs();
            		localFile.createNewFile();
            	}
                
                /** 第一种,通过byte[] file.getBytes(),FileUtils直接把bytes数组写入对应文件李 */
            	byte[] bytes1 = file.getBytes();
            	String filePath1 = uploaddir + "/"+ LocalDate.now().toString() +"/"+ file.getOriginalFilename()+".1";
            	logger.info("filePath1: " + filePath1);
            	logger.info("byte[]: " + new String(bytes1, "UTF-8"));
            	logger.info("filegetName: " + file.getName());
            	FileUtils.writeByteArrayToFile(new File(filePath1), bytes1);
            	logger.info("FileUtils.writeByteArrayToFile 已经执行!");
            	
            	
                /** 第二种,通过IOUtils通过流拷贝到新的文件中去 */
            	String filePath2 = uploaddir + "/"+ LocalDate.now().toString() +"/"+ file.getOriginalFilename()+".2";
            	logger.info("filePath2: " + filePath2);
            	IOUtils.copy(file.getInputStream(),new FileOutputStream(filePath2));
            	logger.info("IOUtils.copy 已经执行!");

            	
            	/** 第三种,转存文件,直接这样使用会报异常 */
                file.transferTo(localFile);


                result = "文件上传成功";
            } catch (Exception e) {
            	result = "文件上传异常";
                e.printStackTrace();
            }
        } else {
        	result = "文件为空";
        }
        return result;
	}
	
	@RequestMapping("/mutliupload")
	public String mutliUpload(HttpServletRequest request, @RequestParam("file") MultipartFile[] files) {
		String result = "";
		StringBuilder stringBuilder = new StringBuilder();
		for (MultipartFile file : files) {
			try {
				// 文件保存路径 
	            String filePath = uploaddir + "/"+ LocalDate.now().toString() +"/"+ file.getOriginalFilename();
	            File localFile = new File(filePath);
	            if(!localFile.getParentFile().exists()) {
            		localFile.getParentFile().mkdirs();
            	}


	            /** 转存文件,需使用第1,2两种方式来,直接使用 transferTo会有问题 */
	            file.transferTo(localFile);


			} catch (Exception e) {
				stringBuilder.append(file.getOriginalFilename() + " 上传失败!");
                e.printStackTrace();
            }
            
		}
		if(StringUtils.isEmpty(stringBuilder.toString())) {
			result = "上传成功!";
		} else {
			result = stringBuilder.toString();
		}
        return result;
	}
	
	@RequestMapping("/index.html")
	public String index() {
		return "fileupload/index";
	}
	
	@RequestMapping("/signleupload.html")
	public String signleupload() {
		return "fileupload/signleupload";
	}
	
	@RequestMapping("/mutliupload.html")
	public String mutliupload() {
		return "fileupload/mutliupload";
	}
	
	
}

 

 

 

 

java.io.IOException: java.io.FileNotFoundException:

dest 是相对路径,指向 upload/doc20170816162034_001.jpg
file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
因此,实际保存位置为 C:\Users\xxxx\AppData\Local\Temp\tomcat.372873030384525225.8080\work\Tomcat\localhost\ROOT\upload\doc20170816162034_001.jpg

所以改为:使用第1和第2种方式,可以保证文件上传,如果直接使用file.transferTo会有文件不存在的异常。

 

还由一个解决方法是file.transferTo()的目标文件可以先new File(xxxx/xxxx/xxx).getAbsolutePath();这样也是获取的觉得路径,windowns绝对路径C:\\xx ,D:\\xx 开头,linux绝对路径以 /xx/xxx/开头。

@Value("${file.upload.path}")
private String path = "upload/";
String fileName = file.getOriginalFilename(); 
File dest = new File(new File(path).getAbsolutePath()+ "/" + fileName); 
file.transferTo(dest); // 保存文件 

 

个人觉得如果是在确认目标文件后,可以直接使用IOUtils.copy进行流拷贝,即第二种方案,第一种只适合小文件,占内存,file.transferTo内部也是流拷贝。也不麻烦。

 

https://blog.csdn.net/SummerX_Z_Y/article/details/107807184

https://blog.csdn.net/qq_44343988/article/details/107826498

接收不到文件的写法
--html
var files = document.getElementById('myFile').files;
var formData = new FormData();
formData.append('file', files);
这样写,后台的

@RequestParam("file")MultipartFile[] file
file始终是获取不到文件的

正确写法
--html
for(i=0; i < files.length; i++){
     formData.append('file', files[i]);
}

 

 

---下载---

response.addHeader("Content-Type", "application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".xlsx;filename*=UTF-8''" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));

 

//1.设置文件ContentType类型,这样设置,会自动判断下载文件类型   
response.setContentType("multipart/form-data");   
//2.设置文件头:最后一个参数是设置下载文件名(假如我们叫a.pdf)   
response.setHeader("Content-Disposition", "attachment;fileName="+"a.pdf");
application/force-download
@RequestMapping(value = "/weChatDown/{fileId}")
public ResponseEntity<byte[]> weChatFiledownload(@PathVariable("fileId") String fileId, HttpServletResponse response, HttpServletRequest request) throws Exception {
    DsCmsFile dsCmsFile = fileService.get(fileId);
    if (dsCmsFile != null) {
        String filePath = dsCmsFile.getFileUrl();
        String fileName = dsCmsFile.getFileName();
        File file = new File(filePath);
        long size = file.length();
        //为了解决中文名称乱码问题 这里是设置文件下载后的名称
        fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
        response.reset();
        response.setHeader("Accept-Ranges", "bytes");
        //设置文件下载是以附件的形式下载
        response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
        response.addHeader("Content-Length", String.valueOf(size));

        ServletOutputStream sos = response.getOutputStream();
        FileInputStream in = new FileInputStream(file);
        BufferedOutputStream outputStream = new BufferedOutputStream(sos);
        byte[] b = new byte[1024];
        int i = 0;
        while ((i = in.read(b)) > 0) {
            outputStream.write(b, 0, i);
        }
        outputStream.flush();
        sos.close();
        outputStream.close();
        in.close();
    }
    return new ResponseEntity<>(HttpStatus.OK);

}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章