Spring Boot 实现本地文件上传

2023年09月23日

1、 设置上传文件配置 application.yml

spring
	servlet:
    	multipart:
     	 	max-file-size: 5MB
      		max-request-size: 10MB
# 上传目录
file:
	upload-dir: /Users/jasonz/Downloads/qxt

2、 配置类

  FileStorageProperties

import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
   private String uploadDir;
   public String getUploadDir() {
       return uploadDir;
   }
   public void setUploadDir(String uploadDir) {
       this.uploadDir = uploadDir;
   }
}

 

3、在应用程序开启读取配置

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 class FileDemoApplication {
   public static void main(String[] args) {
       SpringApplication.run(FileDemoApplication.class, args);
   }
}

  4、控制器 

FileController

import com.example.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.core.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 {
   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<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
       // Load file as Resource
       Resource resource = fileStorageService.loadFileAsResource(fileName);
       // Try to determine file's content type
       String contentType = null;
       try {
           contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
       } catch (IOException ex) {
           logger.info("Could not determine file type.");
       }
       // Fallback to the default content type if type could not be determined
       if(contentType == null) {
           contentType = "application/octet-stream";
       }
       return ResponseEntity.ok()
               .contentType(MediaType.parseMediaType(contentType))
               .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
               .body(resource);
   }
}

 

5、Response 类 

UploadFileResponse

public class UploadFileResponse {
   private String fileName;
   private String fileDownloadUri;
   private String fileType;
   private 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)
}

6、 服务类 FileStorageService
import com.example.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.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 java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
@Service
public class FileStorageService {
   private final Path fileStorageLocation;
   @Autowired
   public FileStorageService(FileStorageProperties fileStorageProperties) {
       this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
               .toAbsolutePath().normalize();
       try {
           Files.createDirectories(this.fileStorageLocation);
       } catch (Exception ex) {
           throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
       }
   }
   public String storeFile(MultipartFile file) {
       // Normalize file name
       String fileName = StringUtils.cleanPath(file.getOriginalFilename());
       try {
           // Check if the file's name contains invalid characters
           if(fileName.contains("..")) {
               throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
           }
           // Copy 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;
       } catch (IOException ex) {
           throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
       }
   }
   public Resource loadFileAsResource(String fileName) {
       try {
           Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
           Resource resource = new UrlResource(filePath.toUri());
           if(resource.exists()) {
               return resource;
           } else {
               throw new MyFileNotFoundException("File not found " + fileName);
           }
       } catch (MalformedURLException ex) {
           throw new MyFileNotFoundException("File not found " + fileName, ex);
       }
   }
}

7、异常类  

FileStorageException

public class FileStorageException extends RuntimeException {
   public FileStorageException(String message) {
       super(message);
   }
   public FileStorageException(String message, Throwable cause) {
       super(message, cause);
   }
}

 

MyFileNotFoundException

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class MyFileNotFoundException extends RuntimeException {
   public MyFileNotFoundException(String message) {
       super(message);
   }
   public MyFileNotFoundException(String message, Throwable cause) {
       super(message, cause);
   }
}

 

© 1987 - 2023 张晓刚 版权所有

浙ICP备16002143号-1