Java實(shí)現(xiàn)文件上傳到服務(wù)器本地并通過(guò)url訪問(wèn)的方法步驟
一、場(chǎng)景
Java實(shí)現(xiàn)文件上傳到服務(wù)器本地,并通過(guò)url訪問(wèn)
有個(gè)需求,前端上傳文件,需要用開(kāi)關(guān)的方式同時(shí)支持上傳七牛和服務(wù)器本地,方便不同的用戶需求合理分配資源。本篇主要介紹文件上傳到本地,然后通過(guò)url訪問(wèn)。
二、SpringBoot默認(rèn)靜態(tài)資源訪問(wèn)方式
首先想到的就是可以通過(guò)SpringBoot通常訪問(wèn)靜態(tài)資源的方式,當(dāng)訪問(wèn):項(xiàng)目根路徑 + / + 靜態(tài)文件名時(shí),SpringBoot會(huì)依次去類(lèi)路徑下的四個(gè)靜態(tài)資源目錄下查找(默認(rèn)配置)。

在資源文件resources目錄下建立如下四個(gè)目錄:

重啟Spring boot,訪問(wèn)
http://localhost:8080/1.jpg
http://localhost:8080/2.jpg
http://localhost:8080/3.jpg
http://localhost:8080/4.jpg
結(jié)果:

三、上傳的文件應(yīng)該存儲(chǔ)在哪?怎么訪問(wèn)?
1.文件存儲(chǔ)在哪?
前文所說(shuō)外部用戶可通過(guò)url訪問(wèn)服務(wù)器資源文件resources目錄下的靜態(tài)資源,但若是將上傳的文件都保存在resources相關(guān)目錄下,將會(huì)導(dǎo)致后續(xù)打包過(guò)大,程序和代碼不分離,無(wú)法查看等問(wèn)題。
解決方案:文件上傳到服務(wù)器某個(gè)目錄,然后SpringBoot配置虛擬路徑,映射到此目錄。
2.怎么訪問(wèn)?
通過(guò)WebMvcConfigurer 的addResourceHandlers將匹配上虛擬路徑的url映射到文件上傳到服務(wù)器的目錄,這樣就可以通過(guò)url來(lái)獲取服務(wù)器上的靜態(tài)資源了。
示例代碼
目標(biāo):windows本地測(cè)試,將文件上傳到 D:\develop\work\project\myblog\myblog-file-upload\fileStorage 目錄下,然后通過(guò)http://localhost:8080/files/文件名 訪問(wèn)。
配置類(lèi)
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
FileServiceImpl fileService;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//將匹配上/files/**虛擬路徑的url映射到文件上傳到服務(wù)器的目錄,獲取靜態(tài)資源
registry.addResourceHandler("/" + fileService.pathPattern + "/**").addResourceLocations("file:" + fileService.filePath);
WebMvcConfigurer.super.addResourceHandlers(registry);
}
}
Controller
@RestController
@RequestMapping("/file")
public class FileController {
@Autowired
private FileServiceImpl fileService;
@PostMapping("/upload")
public FileUploadResponse upload(@RequestParam("file") MultipartFile file) {
return fileService.upload(file);
}
}
上傳文件目錄創(chuàng)建好后,主要通過(guò) file.transferTo(new File(absolutePath)) 完成。
Service
@Slf4j
@Service
public class FileServiceImpl {
//攔截的url,虛擬路徑
public String pathPattern = "files";
//自己設(shè)置的目錄
private static final String fileDir = "fileStorage";
//上傳文件存放目錄 = 工作目錄絕對(duì)路徑 + 自己設(shè)置的目錄,也可以直接自己指定服務(wù)器目錄
//windows本地測(cè)試
//絕對(duì)路徑: D:\develop\work\project\myblog\myblog-file-upload\fileStorage\202302021010345680.jpg
//System.getProperty("user.dir") D:\develop\work\project\myblog\myblog-file-upload
//fileDir fileStorage
//fileName 202302021010345680.jpg
public String filePath = System.getProperty("user.dir") + File.separator + fileDir + File.separator;
private static final AtomicInteger SUFFIX = new AtomicInteger(0);
@Value(value = "${file.upload.suffix:jpg,jpeg,png,bmp,xls,xlsx,pdf}")
private String fileUploadSuffix;
public FileUploadResponse upload(MultipartFile file) {
FileUploadResponse result = new FileUploadResponse();
if (file.isEmpty()) {
log.error("the file to be uploaded is empty");
return result;
}
List<String> suffixList = Lists.newArrayList(fileUploadSuffix.split(","));
try {
//校驗(yàn)文件后綴
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
if (!suffixList.contains(suffix)) {
log.error("unsupported file format");
return result;
}
//首次需生成目錄
File folder = new File(filePath);
if (!folder.exists()) {
folder.mkdirs();
}
String fileName = timeFormat(System.currentTimeMillis()) + SUFFIX.getAndIncrement() + "." + suffix;
String absolutePath = filePath + fileName;
log.info("absolutePath is {}", absolutePath);
file.transferTo(new File(absolutePath));
String separator = "/";
String path = separator + pathPattern + separator + fileName;
result.setPath(path);
result.setFileName(fileName);
} catch (Exception e) {
log.error("the file upload error occurred. e ", e);
}
return result;
}
public static String timeFormat(Long time) {
if (Objects.isNull(time)) {
return null;
}
DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
return sdf.format(time);
}
}四、測(cè)試

查看文件夾,已上傳成功

將上傳接口返回的path拼接上域名或者ip端口、訪問(wèn) http://localhost:8080/files/202302021010345680.jpg,得到:

五、總結(jié)
其實(shí)這和最初的SpringBoot獲取靜態(tài)資源的方式又有點(diǎn)不一樣,針對(duì)url做攔截,實(shí)際上resources目錄下并沒(méi)有files這個(gè)文件夾,它只是一個(gè)虛擬路徑,通過(guò)映射轉(zhuǎn)發(fā)到文件夾上傳目錄,在該目錄下通過(guò)文件名去定位。
另外,如果有用nginx,也可以在其配置中設(shè)置轉(zhuǎn)發(fā)。
到此這篇關(guān)于Java實(shí)現(xiàn)文件上傳到服務(wù)器本地并通過(guò)url訪問(wèn)的文章就介紹到這了,更多相關(guān)Java文件上傳到服務(wù)器本地并訪問(wèn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JavaWeb踩坑記錄之項(xiàng)目訪問(wèn)不到html文件
- 使用Java7的Files工具類(lèi)和Path接口來(lái)訪問(wèn)文件的方法
- Java編程利用socket多線程訪問(wèn)服務(wù)器文件代碼示例
- Spring MVC訪問(wèn)靜態(tài)文件_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java class文件格式之訪問(wèn)標(biāo)志信息_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java訪問(wèn)Hadoop分布式文件系統(tǒng)HDFS的配置說(shuō)明
- Java文件拒絕訪問(wèn)問(wèn)題及解決
相關(guān)文章
java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法
這篇文章主要介紹了java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
java操作gaussDB數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例
本文主要介紹了java操作gaussDB數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
response.sendRedirect()實(shí)現(xiàn)重定向(頁(yè)面跳轉(zhuǎn))
在Java web開(kāi)發(fā)中,使用response.sendRedirect()可實(shí)現(xiàn)重定向功能。本文將介紹如何使用該方法進(jìn)行頁(yè)面跳轉(zhuǎn),以及該方法的使用場(chǎng)景和注意事項(xiàng),感興趣的可以了解一下2023-04-04
Spring ApplicationListener監(jiān)聽(tīng)器用法詳解
這篇文章主要介紹了Spring ApplicationListener監(jiān)聽(tīng)器用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java 數(shù)據(jù)結(jié)構(gòu)七大排序使用分析
這篇文章主要介紹了Java常用的排序算法及代碼實(shí)現(xiàn),在Java開(kāi)發(fā)中,對(duì)排序的應(yīng)用需要熟練的掌握,這樣才能夠確保Java學(xué)習(xí)時(shí)候能夠有扎實(shí)的基礎(chǔ)能力。那Java有哪些排序算法呢?本文小編就來(lái)詳細(xì)說(shuō)說(shuō)Java常見(jiàn)的排序算法,需要的朋友可以參考一下2022-04-04
Java后端請(qǐng)求接收多個(gè)對(duì)象入?yún)⒌臄?shù)據(jù)方法(推薦)
本文介紹了如何使用SpringBoot框架接收多個(gè)對(duì)象作為HTTP請(qǐng)求的入?yún)?通過(guò)創(chuàng)建數(shù)據(jù)模型、DTO類(lèi)和Controller,我們可以輕松處理復(fù)雜的請(qǐng)求數(shù)據(jù)2024-11-11
Java生成隨機(jī)數(shù)之Random與ThreadLocalRandom性能比較詳解
大家項(xiàng)目中如果有生成隨機(jī)數(shù)的需求,我想大多都會(huì)選擇使用Random來(lái)實(shí)現(xiàn),它內(nèi)部使用了CAS來(lái)實(shí)現(xiàn)。?實(shí)際上,JDK1.7之后,提供了另外一個(gè)生成隨機(jī)數(shù)的類(lèi)ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?本文就來(lái)詳細(xì)說(shuō)說(shuō)2022-12-12

