最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)本地上傳文件到resources目錄

 更新時(shí)間:2023年07月24日 16:03:01   作者:咖啡教室  
Java后端項(xiàng)目上傳文件是一個(gè)很常見的需求,這篇文章主要為大家介紹了SpringBoot如何實(shí)現(xiàn)本地上傳文件到resources目錄永久保存下載,需要的可以參考一下

需求背景:Java后端項(xiàng)目上傳文件是一個(gè)很常見的需求,一般正式項(xiàng)目中我們上傳文件都是利用第三方阿里云OSS這類的,但是如果只是為了學(xué)習(xí)之用,那我們可能就會(huì)直接上傳到電腦上某個(gè)本地文件夾。

但是上傳到自己電腦上某個(gè)文件夾,那換一臺(tái)電腦就看不到了,還有一般文件上傳之后我們還需要返回給前端文件的下載路徑,如果是電腦上隨便某個(gè)文件夾,那前端很可能是訪問不到的。

為了解決前端訪問這個(gè)問題,我們可以把文件上傳到后端服務(wù)的靜態(tài)資源目錄里,這樣前端就可以直接通過(guò)后端服務(wù)的地址和端口加上資源路徑來(lái)訪問了。

實(shí)現(xiàn)思路

上傳文件的路徑我們可以用 ResourceUtils.getURL("classpath:").getPath() 這個(gè)方法來(lái)獲取,拿到的就是編譯后的 target/classes 目錄的絕對(duì)路徑,前端上傳的文件就可以直接存到這個(gè)下面的目錄,比如:target/classes/upload/logo.jpg,給前端返回的下載地址就像這樣的:http://localhost:8080/upload/logo.jpg。

上面的思路確實(shí)解決了上傳和下載的問題,但是 target 目錄是會(huì)變動(dòng)的,而且不會(huì)提交到代碼倉(cāng)庫(kù),如果我們清理后再重新編譯或者換臺(tái)電腦編譯,之前上傳的文件就都沒了。

這可怎么辦呢?仔細(xì)一想我們項(xiàng)目不是有一個(gè)叫 resources 用來(lái)存放靜態(tài)資源的目錄嗎,這個(gè)目錄正常也會(huì)提交到代碼倉(cāng)庫(kù)進(jìn)行管理的,那我們每次上傳的文件不就可以一塊提交到倉(cāng)庫(kù)里,這部就實(shí)現(xiàn)了永久保存。

說(shuō)干就干,就直接將文件保存到 resources/upload 目錄下,后端一run前端一上傳,文件確實(shí)被保存到了 resources/upload 目錄下。再仔細(xì)一看不對(duì),前端的地址沒發(fā)訪問剛上傳的文件,因?yàn)?target/classes 目錄下壓根沒有剛上傳的文件,重新點(diǎn)一次 compile 編譯后將 resources 目錄下的文件同步到了 target/classes 目錄下確實(shí)可以實(shí)現(xiàn)訪問,但是總不能我們每次上傳后都要自己重新點(diǎn)一下編譯重新運(yùn)行吧。

最后一合計(jì),那我把resources和target結(jié)合一下,將文件同時(shí)保存到這兩個(gè)目錄下,是不是就可以實(shí)現(xiàn)永久保存和實(shí)時(shí)訪問了呢。

終極方案

用System.getProperty("user.dir")可以獲取到項(xiàng)目的工作目錄,再拼上項(xiàng)目的結(jié)構(gòu)目錄就可以拿到 resources 目錄的絕對(duì)路徑;target/classes 運(yùn)行目錄可以用 ResourceUtils.getURL("classpath:").getPath() 獲取。

注意如果最后上傳的資源目錄訪問404,要看下 application.yml 里 spring.mvn 的靜態(tài)資源路徑,pom.xml里的 resources過(guò)濾規(guī)則,還有 WebMvcConfiguration 里配置的 addResourceHandler 靜態(tài)資源攔映射有沒有攔截掉。

最后前端傳過(guò)來(lái)的是一個(gè) File 文件,但是一個(gè)文件其實(shí)是沒辦法循環(huán)去保存到多個(gè)目錄下的,第一個(gè)文件夾保存成功后后面的都會(huì)報(bào)錯(cuò),想一下我們平時(shí)在電腦上保存一個(gè)文件也只能保存到一個(gè)目錄下,再要保存到其他目錄則自己復(fù)制一份過(guò)去就好了,這里也是一樣第一個(gè)目錄我們直接保存,第二個(gè)則可以用 spring 提供的 FileCopyUtils.copy 直接復(fù)制文件就可以了。

完整代碼

UploadFileUtil.java

package com.sky.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
public class UploadFileUtil {
    /**
     * 獲取文件保存路徑
     *
     * @return File
     * @throws FileNotFoundException
     */
    static List<File> getUploadDirectory() throws FileNotFoundException {
        // 開發(fā)環(huán)境獲取 target/classes 目錄:清理重新編譯后就沒有了
        File targetPath = new File(ResourceUtils.getURL("classpath:").getPath());
        // System.out.printf("項(xiàng)目運(yùn)行的絕對(duì)路徑:" + path.getAbsolutePath());
        // 輸出 xx/sky-parent/sky-server/target/classes
        // 生產(chǎn)環(huán)境 不存在 target/classes 目錄
        if (!targetPath.exists()) {
            // 獲取當(dāng)前運(yùn)行目錄
            targetPath = new File("");
        }
        // 開發(fā)環(huán)境 resources 目錄:可永久保存
        String resourcesPath = System.getProperty("user.dir") + "/sky-server/src/main/resources";
        // System.out.printf("resources目錄路徑:" + resourcesPath);
        File path = new File(resourcesPath);
        File upload = new File(path.getAbsolutePath(), "upload");
        File uploadTarget = new File(targetPath.getAbsolutePath(), "upload");
        // 不存在則創(chuàng)建
        if (!upload.exists()) {
            upload.mkdirs();
        }
        if (!uploadTarget.exists()) {
            uploadTarget.mkdirs();
        }
        List<File> files = new ArrayList<File>();
        files.add(upload);
        files.add(uploadTarget);
        // System.out.printf("當(dāng)前目錄:" + files);
        return files;
    }
    public static String upload(MultipartFile myFile, String dir) throws IOException {
        String filePath = "";
        if (!myFile.isEmpty()) {
            try {
                String filename = myFile.getOriginalFilename();
                filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
                // 之所以保存到 resources 和 target 兩個(gè)目錄,兼顧開發(fā)測(cè)試和永久保存
                // 只保存到resources目錄下每次上傳了要重新編譯下,target則清理打包后就沒有了
                List<File> files = getUploadDirectory();
                // 注意這里一個(gè)文件不能循環(huán)同時(shí)寫入多個(gè)目錄,保存了第一個(gè),第二個(gè)要復(fù)制過(guò)去
                File curFile = new File(files.get(0), filename);
                myFile.transferTo(curFile);
                FileCopyUtils.copy(curFile, new File(files.get(1), filename));
                //for (File f: files) {
                    //File curFile = new File(f, filename);
                    //myFile.transferTo(curFile);
                //}
                filePath = "http://localhost:8080/upload/" + filename;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }
}

application.yml

server:
  port: 8080
spring:
  mvc:
    static-path-pattern: /upload/**

WebMvcConfiguration

package com.sky.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
/**
 * 配置類,注冊(cè)web層相關(guān)組件
 */
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    /**
     * 設(shè)置靜態(tài)資源映射
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 設(shè)置上傳的文件靜態(tài)資源映射,application 里的 mvc 里也要設(shè)置下靜態(tài)目錄
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("classpath:/upload/", "file:upload/");
    }
}

使用示例

在 controller 接收前端用表單上傳的 File 文件

package com.sky.controller.common;
import com.sky.result.Result;
import com.sky.utils.UploadFileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
 * 公共請(qǐng)求
 */
@RestController
@RequestMapping("/common")
@Api(tags = "公共")
@Slf4j
public class CommonController {
    @PostMapping("/upload")
    @ApiOperation("上傳文件")
    public Result uploadFile(MultipartFile file) throws IOException {
        log.info("上傳文件:{}", file);
        String fileUrl = UploadFileUtil.upload(file, "");
        if (fileUrl == null || fileUrl == "") {
            return Result.error("上傳失敗");
        }
        return Result.success(fileUrl);
    }
}

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)本地上傳文件到resources目錄的文章就介紹到這了,更多相關(guān)SpringBoot上傳文件resources目錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在java中實(shí)現(xiàn)C#語(yǔ)法里的按引用傳遞參數(shù)的方法

    在java中實(shí)現(xiàn)C#語(yǔ)法里的按引用傳遞參數(shù)的方法

    下面小編就為大家?guī)?lái)一篇在java中實(shí)現(xiàn)C#語(yǔ)法里的按引用傳遞參數(shù)的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • Spring Security的持久化用戶和授權(quán)實(shí)現(xiàn)方式

    Spring Security的持久化用戶和授權(quán)實(shí)現(xiàn)方式

    文章介紹了如何使用JdbcUserDetailsManager實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀取用戶,并展示了如何配置SpringSecurity進(jìn)行授權(quán)管理,通過(guò)創(chuàng)建數(shù)據(jù)庫(kù)表、配置數(shù)據(jù)庫(kù)連接和修改SecurityConfig,實(shí)現(xiàn)了用戶權(quán)限的控制
    2025-02-02
  • Java?Stream流常用方法實(shí)戰(zhàn)指南

    Java?Stream流常用方法實(shí)戰(zhàn)指南

    Stream流是Java 8中的一個(gè)新特性,它提供了一種處理集合和數(shù)組的方式,Stream流可以讓我們以一種更加簡(jiǎn)潔、高效、可讀性更強(qiáng)的方式來(lái)處理數(shù)據(jù),這篇文章主要介紹了Java?Stream流常用方法的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • Eclipse?2022?設(shè)置中文漢化的超詳細(xì)圖文教程

    Eclipse?2022?設(shè)置中文漢化的超詳細(xì)圖文教程

    這篇文章主要介紹了Eclipse?2022?設(shè)置中文漢化的超詳細(xì)圖文教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • Log4j 配置日志打印時(shí)區(qū)的實(shí)現(xiàn)方法

    Log4j 配置日志打印時(shí)區(qū)的實(shí)現(xiàn)方法

    下面小編就為大家分享一篇Log4j 配置日志打印時(shí)區(qū)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 詳解RestTemplate?用法

    詳解RestTemplate?用法

    RestTemplate?是從?Spring3.0?開始支持的一個(gè)?HTTP?請(qǐng)求工具,也有的稱之為網(wǎng)絡(luò)框架,說(shuō)白了就是Java版本的一個(gè)postman,這篇文章主要介紹了詳解RestTemplate?用法,需要的朋友可以參考下
    2022-07-07
  • Spring中@Configuration注解和@Component注解的區(qū)別詳解

    Spring中@Configuration注解和@Component注解的區(qū)別詳解

    這篇文章主要介紹了Spring中@Configuration注解和@Component注解的區(qū)別詳解,@Configuration 和 @Component 到底有何區(qū)別呢?我先通過(guò)如下一個(gè)案例,在不分析源碼的情況下,小伙伴們先來(lái)直觀感受一下這兩個(gè)之間的區(qū)別,需要的朋友可以參考下
    2023-09-09
  • 深入理解Java中1是true0是false

    深入理解Java中1是true0是false

    Java中,1可以被看作是true,0可以被看作是false,本文就來(lái)進(jìn)行詳細(xì)的講解,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Java順序表實(shí)現(xiàn)圖書管理系統(tǒng)

    Java順序表實(shí)現(xiàn)圖書管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java順序表實(shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 高并發(fā)計(jì)數(shù)器LongAdder 實(shí)現(xiàn)原理與使用場(chǎng)景詳解

    高并發(fā)計(jì)數(shù)器LongAdder 實(shí)現(xiàn)原理與使用場(chǎng)景詳解

    這篇文章主要介紹了高并發(fā)計(jì)數(shù)器LongAdder 實(shí)現(xiàn)原理與使用場(chǎng)景詳解,通過(guò)理解 LongAdder 的設(shè)計(jì)哲學(xué)和實(shí)現(xiàn)細(xì)節(jié),開發(fā)者可以在高并發(fā)場(chǎng)景中做出更優(yōu)的技術(shù)選型,在保證線程安全的前提下實(shí)現(xiàn) 5-10 倍的性能提升,需要的朋友可以參考下
    2025-06-06

最新評(píng)論

句容市| 进贤县| 潜江市| 河曲县| 丘北县| 华池县| 祥云县| 尤溪县| 梁平县| 中山市| 饶河县| 宁都县| 屏南县| 溧水县| 鸡泽县| 报价| 扎赉特旗| 徐闻县| 仁化县| 宁海县| 营山县| 峨眉山市| 杭锦旗| 蓝田县| 满洲里市| 阜康市| 海淀区| 阳新县| 江川县| 新邵县| 潞西市| 农安县| 文登市| 衡水市| 耿马| 清丰县| 江西省| 蓬安县| 葫芦岛市| 金沙县| 乐山市|