1、pom.xml文件
< ? xml version= "1.0" encoding= "UTF-8" ? >
< project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns: xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0 .0 < / modelVersion>
< parent>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- parent< / artifactId>
< version> 2.7 .3 < / version>
< relativePath/ > < ! -- lookup parent from repository -- >
< / parent>
< groupId> com. coffee< / groupId>
< artifactId> file- demo< / artifactId>
< version> 0.0 .1 - SNAPSHOT< / version>
< name> file- demo< / name>
< properties>
< java. version> 1.8 < / java. version>
< commons- fileupload. version> 1.4 < / commons- fileupload. version>
< commons- io. version> 2.11 .0 < / commons- io. version>
< / properties>
< dependencies>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- thymeleaf< / artifactId>
< / dependency>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- web< / artifactId>
< / dependency>
< dependency>
< groupId> commons- fileupload< / groupId>
< artifactId> commons- fileupload< / artifactId>
< version> ${ commons- fileupload. version} < / version>
< / dependency>
< dependency>
< groupId> commons- io< / groupId>
< artifactId> commons- io< / artifactId>
< version> ${ commons- io. version} < / version>
< / dependency>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- devtools< / artifactId>
< ! -- 启用 -- >
< optional> true < / optional>
< / dependency>
< / dependencies>
< build>
< plugins>
< plugin>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- maven- plugin< / artifactId>
< / plugin>
< / plugins>
< / build>
< / project>
2、application.properties
server. port= 8080
spring. thymeleaf. enabled= true
spring. thymeleaf. cache= false
spring. thymeleaf. prefix= classpath: / templates/
spring. thymeleaf. suffix= . html
spring. servlet. multipart. enabled= true
# Single file max size
spring. servlet. multipart. max- file- size= 1024 MB
# All files max size
spring. servlet. multipart. max- request- size= 2048 MB
3、主启动类
@SpringBootApplication
public class FileDemoApplication {
public static void main ( String [ ] args) {
SpringApplication . run ( FileDemoApplication . class , args) ;
}
}
4、自定义线程池
import org. springframework. context. annotation. Bean ;
import org. springframework. context. annotation. Configuration ;
import java. util. concurrent. Executors ;
import java. util. concurrent. LinkedBlockingQueue ;
import java. util. concurrent. ThreadPoolExecutor ;
import java. util. concurrent. TimeUnit ;
@Configuration
public class ThreadPoolConfig {
private static final Integer CPU_NUM = Runtime . getRuntime ( ) . availableProcessors ( ) ;
@Bean
public ThreadPoolExecutor customizeThreadPoolExecutor ( ) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor (
CPU_NUM,
CPU_NUM * 2 ,
5L , TimeUnit . SECONDS,
new LinkedBlockingQueue < > ( CPU_NUM * 4 ) ,
Executors . defaultThreadFactory ( ) ,
new ThreadPoolExecutor. AbortPolicy ( ) ) ;
threadPoolExecutor. allowCoreThreadTimeOut ( true ) ;
return threadPoolExecutor;
}
}
5、controller
import org. apache. commons. io. IOUtils ;
import org. springframework. http. HttpHeaders ;
import org. springframework. http. HttpStatus ;
import org. springframework. http. ResponseEntity ;
import org. springframework. stereotype. Controller ;
import org. springframework. util. ResourceUtils ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. PostMapping ;
import org. springframework. web. bind. annotation. RequestParam ;
import org. springframework. web. multipart. MultipartFile ;
import sun. misc. BASE64Encoder ;
import javax. servlet. ServletOutputStream ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import java. io. File ;
import java. io. FileInputStream ;
import java. io. IOException ;
import java. net. URLEncoder ;
import java. nio. charset. StandardCharsets ;
import java. time. LocalDate ;
import java. time. format. DateTimeFormatter ;
import java. util. Arrays ;
import java. util. concurrent. ThreadPoolExecutor ;
@Controller
public class FileController {
private static final String FIREFOX = "Firefox" ;
private final ThreadPoolExecutor poolExecutor;
public FileController ( ThreadPoolExecutor threadPoolExecutor) {
this . poolExecutor = threadPoolExecutor;
}
@PostMapping ( "/fileUpload" )
public ResponseEntity < String > uploadFiles ( MultipartFile [ ] files) throws IOException {
if ( files. length > 0 ) {
String parentFilePath = LocalDate . now ( ) . format ( DateTimeFormatter . ISO_LOCAL_DATE) ;
String path = "D:" + File . separator + parentFilePath;
File filePath = new File ( path) ;
boolean folderExisted = filePath. exists ( ) || filePath. mkdirs ( ) ;
if ( ! folderExisted) {
throw new IOException ( "Unable to create path" ) ;
}
Arrays . asList ( files) . forEach ( file -> poolExecutor. execute ( ( ) -> {
try {
file. transferTo ( new File ( path + File . separator + file. getOriginalFilename ( ) ) ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
} ) ) ;
} else {
return new ResponseEntity < > ( "没有文件可上传" , HttpStatus . OK) ;
}
return new ResponseEntity < > ( "文件上传成功" , HttpStatus . OK) ;
}
@GetMapping ( "/download" )
public void download ( @RequestParam ( "fileName" ) String fileName, HttpServletRequest request, HttpServletResponse response) {
try {
String realPath = ResourceUtils . getURL ( "classpath:" ) . getPath ( ) + "/static/files" ;
File file = new File ( realPath, fileName) ;
FileInputStream inputStream = new FileInputStream ( file) ;
ServletOutputStream outputStream = response. getOutputStream ( ) ;
String agent = request. getHeader ( HttpHeaders . USER_AGENT) ;
if ( agent. contains ( FIREFOX) ) {
fileName = new BASE64Encoder ( ) . encode ( fileName. getBytes ( StandardCharsets . UTF_8) ) ;
} else {
fileName = URLEncoder . encode ( fileName, StandardCharsets . UTF_8. name ( ) ) ;
}
response. setCharacterEncoding ( StandardCharsets . UTF_8. name ( ) ) ;
response. setHeader ( HttpHeaders . CONTENT_DISPOSITION,
"attachment;filename=" + URLEncoder . encode ( fileName, StandardCharsets . UTF_8. name ( ) ) ) ;
response. setHeader ( HttpHeaders . CONTENT_LENGTH, String . valueOf ( file. length ( ) ) ) ;
IOUtils . copy ( inputStream, outputStream) ;
IOUtils . closeQuietly ( inputStream) ;
IOUtils . closeQuietly ( outputStream) ;
} catch ( IOException ex) {
ex. printStackTrace ( ) ;
}
}
}
6、前端页面
< ! DOCTYPE html>
< html xmlns: th= "http://www.thymeleaf.org" >
< head>
< ! -- 引入jquery css& js -- >
< script src= "https://code.jquery.com/jquery-3.4.1.min.js" crossorigin= "anonymous" > < / script>
< ! -- 引入bootstrap css& js -- >
< link rel= "stylesheet" href= "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity= "sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin= "anonymous" >
< / head>
< body>
< div class = "container" >
< div class = "row" >
< div class = "col-10 mx-auto" >
< form class = "mt-5" method= "post" enctype= "multipart/form-data" >
< div class = "input-group" >
< div class = "custom-file" >
< input type= "file" class = "custom-file-input" id= "customFile1" name= "file" >
< label class = "custom-file-label" for = "customFile1" data- browse= "选择文件" > 点击选择. . . </ label>
< / div>
< div class = "input-group-append" >
< button type= "button" class = "btn btn-outline-secondary reset" > 重选< / button>
< / div>
< / div>
< div class = "row mt-3" >
< div class = "col-12" >
< div class = "text-center" >
< button type= "submit" id= "uploadFileBtn" class = "btn btn-outline-secondary" > 提交< / button>
< / div>
< / div>
< / div>
< / form>
< ! -- Bootstrap Progress bar -- >
< div class = "progress mt-3" >
< div id= "progressBar" class = "progress-bar progress-bar-success" role= "progressbar"
aria- valuenow= "0" aria- valuemin= "0" aria- valuemax= "100" style= "width: 0%" > 0 %
< / div>
< / div>
< ! -- Bootstrap Alert -- >
< div id= "alertDiv" class = "mt-3 alert alert-warning alert-dismissible fade" role= "alert" >
< span id= "alertMsg" > < / span>
< button id= "closeButton" type= "button" class = "close" data- dismiss= "alert" aria- label= "Close" >
< span aria- hidden= "true" > & times; < / span>
< / button>
< / div>
< / div>
< / div>
< / div>
< ! -- upload. js -- >
< script>
$( '. custom- file- input').on(' change', function ( ) {
$( this ) . next ( '. custom- file- label') . html ( $( this ) [ 0 ] . files[ 0 ] . name) ;
$( 'button[ type= submit] ') . prop ( 'disabled', false ) ;
} ) ;
$( '.reset' ) . click ( function ( ) {
$( this ) . parent ( ) . prev ( ) . children ( '. custom- file- label') . html ( '点击选择. . . ') ;
$( '. custom- file- input').val(' ') ;
$( 'button[ type= submit] ') . prop ( 'disabled', false ) ;
} ) ;
$( "#closeButton" ) . click ( function ( ) {
$( "#alertDiv1" ) . style. visibility= "hidden" ;
} ) ;
$( "#uploadFileBtn" ) . click ( function ( e) {
e. preventDefault ( ) ;
$( this ) . prop ( 'disabled', true ) ;
var file = $( '#customFile') [ 0 ] . files[ 0 ] ;
var formData = new FormData ( ) ;
formData. append ( "file" , file) ;
$. ajax ( {
url: '/ fileUploads',
type: 'POST' ,
data: formData,
cache: false ,
contentType: false ,
processData: false ,
xhr: function ( ) {
var xhr = $. ajaxSettings. xhr ( ) ;
xhr. upload. onprogress = function ( event) {
var perc = Math . round ( ( event. loaded / event. total) * 100 ) ;
$( '#progressBar') . text ( perc + '%' ) ;
$( '#progressBar').css(' width', perc + '%' ) ;
} ;
return xhr;
} ,
beforeSend: function ( xhr) {
$( '#alertMsg1') . text ( '') ;
$( '#progressBar') . text ( '') ;
$( '#progressBar').css(' width', ' 0 % ') ;
}
} )
. done ( function ( msg) {
$( '#alertDiv') . addClass ( "show" ) ;
$( '#alertMsg') . text ( msg) ;
$( 'input[ type= file] ').val(' ') ;
$( 'button[ type= submit] ') . prop ( 'disabled', false ) ;
} )
. fail ( function ( jqXHR) {
$( '#alertDiv') . addClass ( "show" ) ;
$( '#alertMsg') . text ( "发生错误" ) ;
} ) ;
return false ;
} ) ;
< / script>
< / body>
< / html>