java實(shí)現(xiàn)文件上傳的詳細(xì)步驟
一、文件上傳——簡(jiǎn)介
文件上傳的簡(jiǎn)介:文件上傳是指將本地計(jì)算機(jī)中的文件傳輸?shù)骄W(wǎng)絡(luò)上的服務(wù)器或另一臺(tái)計(jì)算機(jī)上的過(guò)程。在 Web 開(kāi)發(fā)中,文件上傳通常指的是將用戶通過(guò) Web 頁(yè)面提交的文件(如圖像、文檔、音頻、視頻等)傳輸?shù)椒?wù)器端的操作。
- 簡(jiǎn)單來(lái)說(shuō),文件上傳是指將本地圖片、視頻、音頻等文件上傳到服務(wù)器上,供其他用戶瀏覽或下載的過(guò)程。
文件上傳通常涉及以下幾個(gè)主要組件:
- 客戶端:指的是文件上傳的發(fā)起方,通常是用戶在 Web 瀏覽器中通過(guò)表單提交文件。
- 服務(wù)器端:指的是接收并處理文件上傳請(qǐng)求的計(jì)算機(jī)系統(tǒng)或服務(wù)器。
- 上傳表單:通過(guò) HTML 表單元素來(lái)實(shí)現(xiàn)文件上傳功能。表單需要設(shè)置 enctype 屬性為 “multipart/form-data”,并包含一個(gè)文件輸入框用于選擇要上傳的文件。
- 文件處理邏輯:服務(wù)器端接收到文件上傳請(qǐng)求后,需要將上傳的文件保存到指定的位置,并可能進(jìn)行進(jìn)一步的處理,如文件存儲(chǔ)、文件重命名、文件格式驗(yàn)證等。
- 文件上傳控制器:在 Web 開(kāi)發(fā)框架中,通常需要編寫(xiě)文件上傳的處理邏輯,這些邏輯通常由服務(wù)器端的控制器或處理器來(lái)處理。
文件上傳在 Web 開(kāi)發(fā)中非常常見(jiàn),常見(jiàn)的應(yīng)用場(chǎng)景包括但不限于用戶頭像上傳、文件分享、數(shù)據(jù)備份等。
二、文件上傳——入門(mén)
文件上傳的步驟:
- 先創(chuàng)建一個(gè)springboot工程(這個(gè)常識(shí)了,不展示了)
- 編寫(xiě)一個(gè)上傳文件的前端html文件
- 編寫(xiě)一個(gè)controller
項(xiàng)目結(jié)構(gòu)
文件上傳前端的三要素:
- 請(qǐng)求方式是:post
- 需要設(shè)置 enctype=“multipart/form-data” 屬性以支持文件上傳
<form>
元素應(yīng)該包含一個(gè)<input type="file">
元素,用于讓用戶選擇要上傳的文件。
編寫(xiě)的html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上傳</title> </head> <body> <h2>上傳文件</h2> <form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="file" id="fileToUpload"> <input type="submit" value="上傳" name="submit"> </form> </body> </html>
編寫(xiě)的controller
package com.knife.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @RestController public class UploadController { @PostMapping("/upload") public void upload(MultipartFile file){ System.out.println("file == " + file); } }
運(yùn)行截圖:(通過(guò)xml配置的路徑去訪問(wèn)html文件,然后點(diǎn)擊上傳文件)
file內(nèi)容不等于null,說(shuō)明文件上傳成功。
總結(jié):服務(wù)端要想接收到從前端頁(yè)面上傳的文件,需要使用到一個(gè)api:MultipartFile,通過(guò)該api來(lái)接收上傳的文件。而上傳上來(lái)的文件是一個(gè)臨時(shí)文件,當(dāng)文件上傳這次請(qǐng)求完成之后,這些臨時(shí)文件會(huì)自動(dòng)刪除。因此,在上傳文件的同時(shí),應(yīng)該把文件保存起來(lái)。
三、文件上傳——本地存儲(chǔ)—第一版
在服務(wù)端,接收到上傳上來(lái)的文件之后,將文件存儲(chǔ)在本地服務(wù)器磁盤(pán)中。
基礎(chǔ)實(shí)現(xiàn):在上面的文件上傳——入門(mén)的基礎(chǔ)上,修改一下controller就行。
package com.knife.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; @RestController public class UploadController { @PostMapping("/upload") public void upload(MultipartFile file) throws IOException { System.out.println("file == " + file); // 獲取源文件的文件名 String originalFilename = file.getOriginalFilename(); // 把上傳上來(lái)的文件存儲(chǔ)到磁盤(pán)上:transferTo的參數(shù)是一個(gè)文件 file.transferTo(new File("E:\\images\\"+ originalFilename)); } }
只需把上面的controller改成上面一樣,然后運(yùn)行,然后如果你的路徑不對(duì),或者你盤(pán)符的目錄不存在,就會(huì)報(bào)錯(cuò)了(因?yàn)檫@里沒(méi)有對(duì)異常處理,只是簡(jiǎn)單地把異常拋出去了)
最快的解決辦法就是,修改本地存儲(chǔ)的路徑,輸入一個(gè)存在的目錄的路徑。
最佳解決辦法:如下更改controller
package com.knife.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @RestController public class UploadController { @PostMapping("/upload") public void upload(MultipartFile file) throws IOException { System.out.println("file == " + file); // 1. 獲取源文件的文件名 String originalFilename = file.getOriginalFilename(); // 定義要上傳的路徑 String fileUploadPath = "E:\\images\\"+ originalFilename; // 創(chuàng)建要上傳的文件 File uploadFile = new File(fileUploadPath); // 判斷配置的文件目錄是否存在,若不存在則創(chuàng)建一個(gè)新的文件目錄 File parentFile = uploadFile.getParentFile(); if(!parentFile.exists()) { parentFile.mkdirs(); } System.out.println(uploadFile); file.transferTo(uploadFile); } }
運(yùn)行:
四、文件上傳——本地存儲(chǔ)—第二版
本地存儲(chǔ)第一版存在的問(wèn)題:
- 解決:保證每一個(gè)文件的文件名是唯一的(文件名不能重復(fù))
- 使用uuid工具(通用唯一標(biāo)識(shí)碼)——使用生成的uuid碼+原始文件名的后綴
- 使用原始文件名進(jìn)行存儲(chǔ)時(shí),如果同時(shí)上傳了文件名一樣的文件,那么后面上傳的文件會(huì)把前面上傳的文件給覆蓋。
- 解決:保證每一個(gè)文件的文件名是唯一的(文件名不能重復(fù))
不管文件路徑的報(bào)錯(cuò)的寫(xiě)法(和上面文件上傳——本地存儲(chǔ)—第一版就只有controller的差別):
package com.knife.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @RestController public class UploadController { @PostMapping("/upload") public void upload(MultipartFile file) throws IOException { System.out.println("file == " + file); // 1. 獲取源文件的文件名 String originalFilename = file.getOriginalFilename(); // 2. 構(gòu)造唯一的文件名 -- 使用uuid(通用唯一識(shí)別碼,長(zhǎng)度固定的字符串,而且是唯一的)+ 原始文件文件后綴名 // 2.1. 通過(guò)字符串的截取,獲取文件的后綴名 int index = originalFilename.lastIndexOf("."); String extname = originalFilename.substring(index); // 2.2 把uuid和文件后綴名合并 String newFileName = UUID.randomUUID().toString() + extname; System.out.println("newFileName = " + newFileName); // 把上傳上來(lái)的文件存儲(chǔ)到磁盤(pán)上:(指定一個(gè)路徑) file.transferTo(new File("E:\\"+ newFileName)); } }
- 解決文件路徑的報(bào)錯(cuò)的寫(xiě)法(和上面文件上傳——本地存儲(chǔ)—第一版就只有controller的差別):
package com.knife.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @RestController public class UploadController { @PostMapping("/upload") public void upload(MultipartFile file) throws IOException { System.out.println("file == " + file); // 1. 獲取源文件的文件名 String originalFilename = file.getOriginalFilename(); // 2. 構(gòu)造唯一的文件名 -- 使用uuid(通用唯一識(shí)別碼,長(zhǎng)度固定的字符串,而且是唯一的)+ 原始文件文件后綴名 // 2.1. 通過(guò)字符串的截取,獲取文件的后綴名 int index = originalFilename.lastIndexOf("."); String extname = originalFilename.substring(index); // 2.2 把uuid和文件后綴名合并 String newFileName = UUID.randomUUID().toString() + extname; // 定義要上傳的路徑 String fileUploadPath = "E:\\images\\"+ newFileName; // 創(chuàng)建要上傳的文件 File uploadFile = new File(fileUploadPath); // 判斷配置的文件目錄是否存在,若不存在則創(chuàng)建一個(gè)新的文件目錄 File parentFile = uploadFile.getParentFile(); if(!parentFile.exists()) { parentFile.mkdirs(); } System.out.println(uploadFile); // 把上傳上來(lái)的文件存儲(chǔ)到磁盤(pán)上:(指定一個(gè)路徑) file.transferTo(uploadFile); } }
運(yùn)行:
文件上傳大小限制的問(wèn)題:在配置文件里面進(jìn)行配置
如果是application.properties則如上圖一樣配置就行,如果是application.yml,則如下配置即可
application.yml:
server: port: 8088 # 配置訪問(wèn)服務(wù)器的端口 spring: servlet: multipart: max-file-size: 10MB # 配置單個(gè)文件最大上傳大小 max-request-size: 100MB # 配置單個(gè)請(qǐng)求最大上傳文件的大?。ㄒ淮慰梢陨蟼鞫鄠€(gè)文件,即多個(gè)文件的總和也算)
- 本地存儲(chǔ)存在的問(wèn)題:
五、文件上傳——對(duì)象存儲(chǔ)——阿里云OOS
1、參照官方SDK編寫(xiě)入門(mén)程序
- 第一步:在Maven工程中使用OSS Java SDK,只需在pom.xml中加入相應(yīng)依賴即可。在
<dependencies>
中加入如下內(nèi)容(參考官方文檔的說(shuō)明):
<dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.15.1</version> </dependency>
- 如果使用的是Java 9及以上的版本,則需要添加JAXB相關(guān)依賴。添加JAXB相關(guān)依賴示例代碼如下:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> <!-- no more than 2.3.3--> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.3</version> </dependency>
- 第二步:復(fù)制上傳文件入門(mén)代碼(官方文檔)官方文檔入門(mén)程序例子:然后再根據(jù)自己的實(shí)際情況改寫(xiě)
import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.PutObjectResult; import java.io.FileInputStream; import java.io.InputStream; public class Demo { public static void main(String[] args) throws Exception { // Endpoint以華東1(杭州)為例,其它Region請(qǐng)按實(shí)際情況填寫(xiě)。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 從環(huán)境變量中獲取訪問(wèn)憑證。運(yùn)行本代碼示例之前,請(qǐng)確保已設(shè)置環(huán)境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // 填寫(xiě)B(tài)ucket名稱,例如examplebucket。 String bucketName = "examplebucket"; // 填寫(xiě)Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。 String objectName = "exampledir/exampleobject.txt"; // 填寫(xiě)本地文件的完整路徑,例如D:\\localpath\\examplefile.txt。 // 如果未指定本地路徑,則默認(rèn)從示例程序所屬項(xiàng)目對(duì)應(yīng)本地路徑中上傳文件流。 String filePath= "D:\\localpath\\examplefile.txt"; // 創(chuàng)建OSSClient實(shí)例。 OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { InputStream inputStream = new FileInputStream(filePath); // 創(chuàng)建PutObjectRequest對(duì)象。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream); // 創(chuàng)建PutObject請(qǐng)求。 PutObjectResult result = ossClient.putObject(putObjectRequest); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
改寫(xiě)后的入門(mén)程序:主要修改自己的endpoint、accessKeyId、bucketName、objectName、filePath
package com.knife; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.PutObjectResult; import java.io.FileInputStream; import java.io.InputStream; public class uploadOss{ public static void main(String[] args) throws Exception { // Endpoint:(華北2(北京))請(qǐng)按實(shí)際情況填寫(xiě)。 String endpoint = "oss-cn-beijing.aliyuncs.com"; // 根據(jù)自己的實(shí)際情況填寫(xiě) // 從環(huán)境變量中獲取訪問(wèn)憑證。運(yùn)行本代碼示例之前,請(qǐng)確保已設(shè)置環(huán)境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 // EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // 使用accessKeyId、accessKeyIdSecret替代。 String accessKeyId = "你自己的密鑰id"; // 根據(jù)自己的實(shí)際情況填寫(xiě) String accessKeyIdSecret ="你自己的密鑰";// 根據(jù)自己的實(shí)際情況填寫(xiě) // 填寫(xiě)B(tài)ucket名稱,例如examplebucket。 String bucketName = "你自己的bucketName";// 根據(jù)自己的實(shí)際情況填寫(xiě) // 填寫(xiě)Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。 String objectName = "1.jpg"; //設(shè)置我們上傳的文件,最終在阿里云上面是什么名字 // 填寫(xiě)本地文件的完整路徑,例如D:\\localpath\\examplefile.txt。 // 如果未指定本地路徑,則默認(rèn)從示例程序所屬項(xiàng)目對(duì)應(yīng)本地路徑中上傳文件流。 String filePath= "C:\\Users\\qq351\\Pictures\\Saved Pictures\\1.jpg"; // 創(chuàng)建OSSClient實(shí)例。 // OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeyIdSecret); try { InputStream inputStream = new FileInputStream(filePath); // 創(chuàng)建PutObjectRequest對(duì)象。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream); // 創(chuàng)建PutObject請(qǐng)求。 PutObjectResult result = ossClient.putObject(putObjectRequest); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
路徑獲?。?/p>
運(yùn)行就可以傳進(jìn)去了
通過(guò)瀏覽器訪問(wèn)該圖片的路徑時(shí),會(huì)直接下載該圖片,但是在頁(yè)面顯示出來(lái)挺簡(jiǎn)單的,就是使用一個(gè)imag標(biāo)簽,然后把路徑放在src下即可
<image src="https://cangqiongwaimaiknife.oss-cn-beijing.aliyuncs.com/1.jpg">
六、在項(xiàng)目中使用OOS文件上傳
- 在項(xiàng)目中,一般會(huì)把文件上傳的方法封裝成一個(gè)工具類(lèi)然后再使用。
在配置文件里面對(duì)oss的參數(shù)進(jìn)行配置
#阿里云OSS aliyun: oss: endpoint: https://oss-cn-hangzhou.aliyuncs.com accessKeyId: LTAI4GCH1vX6DKqJWxd6nEuW accessKeySecret: yBshYweHOpqDuhCArrVHwIiBKpyqSL bucketName: web-tlias
屬性配置類(lèi):(讀取配置文件里面的屬性)
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "aliyun.oss") public class AliOSSProperties { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketName; }
封裝工具類(lèi):
import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.util.UUID; /** * 阿里云 OSS 工具類(lèi) */ @Component public class AliOSSUtils { @Autowired private AliOSSProperties aliOSSProperties; /** * 實(shí)現(xiàn)上傳圖片到OSS */ public String upload(MultipartFile file) throws IOException { //獲取阿里云OSS參數(shù) String endpoint = aliOSSProperties.getEndpoint(); String accessKeyId = aliOSSProperties.getAccessKeyId(); String accessKeySecret = aliOSSProperties.getAccessKeySecret(); String bucketName = aliOSSProperties.getBucketName(); // 獲取上傳的文件的輸入流 InputStream inputStream = file.getInputStream(); // 避免文件覆蓋 String originalFilename = file.getOriginalFilename(); String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf(".")); //上傳文件到 OSS OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ossClient.putObject(bucketName, fileName, inputStream); //文件訪問(wèn)路徑 String url = endpoint.split("http://")[0] + "http://" + bucketName + "." + endpoint.split("http://")[1] + "/" + fileName; // 關(guān)閉ossClient ossClient.shutdown(); return url;// 把上傳到oss的路徑返回 } }
controller類(lèi)上使用
import com.itheima.pojo.Result; import com.itheima.utils.AliOSSUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @RestController public class UploadController { @Autowired private AliOSSUtils aliOSSUtils; @PostMapping("/upload") public Result upload(MultipartFile image) throws IOException { log.info("文件上傳, 文件名: {}", image.getOriginalFilename()); //調(diào)用阿里云OSS工具類(lèi)進(jìn)行文件上傳 String url = aliOSSUtils.upload(image); log.info("文件上傳完成,文件訪問(wèn)的url: {}", url); return Result.success(url); } }
總結(jié)
到此這篇關(guān)于java實(shí)現(xiàn)文件上傳的文章就介紹到這了,更多相關(guān)java文件上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入了解Java設(shè)計(jì)模式之UML類(lèi)圖
UML?即?Unified?Modeling?Language?統(tǒng)一建模語(yǔ)言,是用來(lái)設(shè)計(jì)軟件的可視化建模語(yǔ)言。本文就帶大家了解一下UML中類(lèi)圖的定義與使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-11-11SpringBoot項(xiàng)目中使用Netty實(shí)現(xiàn)遠(yuǎn)程調(diào)用的示例代碼
眾所周知在進(jìn)行網(wǎng)絡(luò)連接的時(shí)候,建立套接字連接是一個(gè)非常消耗性能的事情,特別是在分布式的情況下,那么該通過(guò)什么技術(shù)去解決上述的問(wèn)題呢,本文小編給大家介紹了SpringBoot項(xiàng)目中使用Netty實(shí)現(xiàn)遠(yuǎn)程調(diào)用的方法,需要的朋友可以參考下2025-04-04Java中JSONObject與JSONArray的使用區(qū)別詳解
這篇文章主要介紹了Java中JSONObject與JSONArray的使用區(qū)別詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11Mybatis框架中Interceptor接口的使用說(shuō)明
這篇文章主要介紹了Mybatis框架中Interceptor接口的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09Java數(shù)據(jù)結(jié)構(gòu)與算法學(xué)習(xí)之循環(huán)鏈表
循環(huán)鏈表是另一種形式的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。它的特點(diǎn)是表中最后一個(gè)結(jié)點(diǎn)的指針域指向頭結(jié)點(diǎn),整個(gè)鏈表形成一個(gè)環(huán)。本文將為大家詳細(xì)介紹一下循環(huán)鏈表的特點(diǎn)與使用,需要的可以了解一下2021-12-12Java使用Thread創(chuàng)建多線程并啟動(dòng)操作示例
這篇文章主要介紹了Java使用Thread創(chuàng)建多線程并啟動(dòng)操作,結(jié)合實(shí)例形式分析了Java基于Thread類(lèi)的多線程定義與啟動(dòng)簡(jiǎn)單操作技巧,需要的朋友可以參考下2018-06-06springboot整合vue實(shí)現(xiàn)上傳下載文件
這篇文章主要為大家詳細(xì)介紹了springboot整合vue實(shí)現(xiàn)上傳下載文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11