欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的MultipartFile接口和File類解讀

 更新時(shí)間:2025年02月11日 11:02:50   作者:執(zhí)念1314  
本文主要介紹了Java中的File類和Spring框架中的MultipartFile接口,File類提供了對(duì)文件和目錄操作的方法,如創(chuàng)建、刪除、重命名、判斷文件是否存在等,MultipartFile接口用于處理文件上傳,提供了獲取上傳文件信息和保存上傳文件的方法

一、File類

java.io.File是 Java 標(biāo)準(zhǔn)庫(kù)中用于操作文件和目錄路徑的類。它提供了很多方法,用于創(chuàng)建、刪除、重命名、判斷文件是否存在、獲取文件信息等操作。

獲取文件信息

  • boolean exists(): 判斷文件或目錄是否存在。
  • boolean isFile(): 判斷是否是文件。
  • boolean isDirectory(): 判斷是否是目錄。
  • String getName(): 獲取文件或目錄的名稱。
  • String getPath(): 獲取文件或目錄的路徑。
  • String getAbsolutePath(): 獲取文件或目錄的絕對(duì)路徑。
  • long length(): 獲取文件的大?。ㄗ止?jié)數(shù))。

文件和目錄操作

  • boolean createNewFile(): 創(chuàng)建新文件。如果文件已存在,則不創(chuàng)建,返回 false。
  • boolean mkdir(): 創(chuàng)建新目錄。如果目錄已存在,則不創(chuàng)建,返回 false。
  • boolean mkdirs(): 創(chuàng)建新目錄及其父目錄,如果不存在的話。
  • boolean delete(): 刪除文件或目錄。

文件路徑操作

  • boolean renameTo(File dest): 重命名文件或目錄。如果成功,返回 true;否則,返回 false。
  • String[] list(): 返回目錄下的文件和目錄名數(shù)組。
  • File[] listFiles(): 返回目錄下的文件和目錄的 File 對(duì)象數(shù)組。

文件過濾

  • String[] list(FilenameFilter filter): 返回目錄下滿足指定過濾器條件的文件和目錄名數(shù)組。
  • File[] listFiles(FileFilter filter): 返回目錄下滿足指定過濾器條件的文件和目錄的 File 對(duì)象數(shù)組。

二、MultipartFile接口

MultipartFile是 Spring 框架提供的一個(gè)接口,用于表示處理文件上傳的對(duì)象。

它通常用于處理multipart/form-data類型的請(qǐng)求,例如處理文件上傳的表單。

首先我們依舊可以通過源碼的學(xué)習(xí)來進(jìn)一步了解這個(gè)接口。

2.1 源碼和方法功能

public interface MultipartFile extends InputStreamSource {
    String getName();
 
    @Nullable
    String getOriginalFilename();
 
    @Nullable
    String getContentType();
 
    boolean isEmpty();
 
    long getSize();
 
    byte[] getBytes() throws IOException;
 
    InputStream getInputStream() throws IOException;
 
    default Resource getResource() {
        return new MultipartFileResource(this);
    }
 
    void transferTo(File dest) throws IOException, IllegalStateException;
 
    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
    }
}
  • String getName():獲取上傳文件的表單字段名稱
  • String getOriginalFilename():獲取上傳文件的原始文件名
  • String getContentType():獲取上傳文件的內(nèi)容類型
  • boolean isEmpty():判斷上傳文件是否為空
  • long getSize():獲取上傳文件的大小,單位是字節(jié)
  • byte[] getBytes() throws IOException:獲取上傳文件的字節(jié)數(shù)組表示
  • InputStream getInputStream() throws IOException:獲取上傳文件的輸入流
  • default Resource getResource() :將 MultipartFile 封裝成了 Resource 對(duì)象,從而可以使用 Resource 接口提供的方法來操作上傳文件的內(nèi)容。
  • void transferTo(File dest) throws IOException, IllegalStateException:將上傳文件保存到指定的文件;
  • default void transferTo(Path dest) throws IOException, IllegalStateException:將上傳文件保存在指定的路徑下;

2.2 void transferTo(File dest)

前面我們已經(jīng)介紹了該方法是Spring中提供的將上傳文件保存到指定的文件中的抽象方法,溯源源碼我們可以看到這個(gè)接口方法被三個(gè)實(shí)現(xiàn)類實(shí)現(xiàn)了,分別是CommonsMultipartFile、MockMultipartFile 和 StandardMultipartHttpServletRequest。

CommonsMultipartFile中的方法體

我們可以看到CommonsMultipartFile中的方法體主要是通過檢測(cè)傳進(jìn)來的文件是否可用、是否存在,并在檢測(cè)完成就執(zhí)行寫入的操作

public void transferTo(File dest) throws IOException, IllegalStateException {
        if (!this.isAvailable()) {
            throw new IllegalStateException("File has already been moved - cannot be transferred again");
        } else if (dest.exists() && !dest.delete()) {
            throw new IOException("Destination file [" + dest.getAbsolutePath() + "] already exists and could not be deleted");
        } else {
            try {
                this.fileItem.write(dest);
                LogFormatUtils.traceDebug(logger, (traceOn) -> {
                    String action = "transferred";
                    if (!this.fileItem.isInMemory()) {
                        action = this.isAvailable() ? "copied" : "moved";
                    }
 
                    return "Part '" + this.getName() + "',  filename '" + this.getOriginalFilename() + "'" + (traceOn ? ", stored " + this.getStorageDescription() : "") + ": " + action + " to [" + dest.getAbsolutePath() + "]";
                });
            } catch (FileUploadException var3) {
                throw new IllegalStateException(var3.getMessage(), var3);
            } catch (IOException | IllegalStateException var4) {
                throw var4;
            } catch (Exception var5) {
                throw new IOException("File transfer failed", var5);
            }
        }
    }

上面這段demo中可能對(duì)于this.isAvailable()有疑問,我們知曉這里的this其實(shí)是該類的實(shí)例化對(duì)象,但是這里的this.isAvailable()就是拿來判斷目的文件是否可用,調(diào)用的就是類的內(nèi)部方法,判斷是否可用的條件就是該目標(biāo)文件是否被加載進(jìn)內(nèi)存中!

這里給出一個(gè)使用該方法的例子,需要注意的是這時(shí)候方法要求的是一個(gè)目標(biāo)File對(duì)象,我們需要在調(diào)用該目標(biāo)方法的時(shí)候就根據(jù)目標(biāo)路徑創(chuàng)建了目標(biāo)的File對(duì)象。

// 獲取上傳文件的原始文件名
String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
 
// 構(gòu)建目標(biāo)文件對(duì)象
File destFile = new File("/path/to/destination/directory", originalFilename);
 
try {
    // 將上傳文件保存到目標(biāo)文件
    file.transferTo(destFile);
    return "File uploaded successfully!";
} catch (IOException e) {
    e.printStackTrace();
    return "Failed to upload the file.";
}

StandardMultipartHttpServletRequest實(shí)現(xiàn)類

而另一個(gè)實(shí)現(xiàn)類StandardMultipartHttpServletRequest和CommonsMultipartFile的區(qū)別就在于使用StandardMultipartHttpServletRequest直接上傳文件的話可能會(huì)出現(xiàn)目錄跳躍的問題,而CommonsMultipartFile不會(huì),這是因?yàn)槠鋵?duì)路勁分隔符了相關(guān)的限制。

default void transferTo(Path dest)

該默認(rèn)方法在實(shí)現(xiàn)類中被重寫了,但主要的功能還是不變,就是將上傳的文件寫入到指定路徑的Path對(duì)象中實(shí)現(xiàn)文件上傳的功能。

這里給出使用的示例代碼:

// 構(gòu)建目標(biāo)文件路徑
String uploadDirectory = "/path/to/destination/directory";
String originalFilename = file.getOriginalFilename();
Path filePath = Paths.get(uploadDirectory, originalFilename);
 
try {
// 將上傳文件保存到目標(biāo)文件
    file.transferTo(filePath);
    return "File uploaded successfully!";
} catch (IOException e) {
    e.printStackTrace();
    return "Failed to upload the file.";
}

實(shí)際項(xiàng)目使用文件上傳和下載

@PostMapping("/file/upload")
    public Result uploadFile(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StrUtil.isBlank(originalFilename)) {
            return Result.error("文件上傳失敗");
        }
        long flag = System.currentTimeMillis();
        String filePath = BASE_FILE_PATH + flag + "_" + originalFilename;
        try {
            FileUtil.mkParentDirs(filePath);  // 創(chuàng)建父級(jí)目錄
            file.transferTo(FileUtil.file(filePath));
            Admin currentAdmin = TokenUtils.getCurrentAdmin();
            String token = TokenUtils.genToken(currentAdmin.getId().toString(), currentAdmin.getPassword(), 15);
            String url = "http://localhost:9090/api/book/file/download/" + flag + "?&token=" + token;
            if (originalFilename.endsWith("png") || originalFilename.endsWith("jpg") || originalFilename.endsWith("pdf")) {
                url += "&play=1";
            }
            return Result.success(url);
        } catch (Exception e) {
            log.info("文件上傳失敗", e);
        }
        return Result.error("文件上傳失敗");
    }

    @GetMapping("/file/download/{flag}")
    public void download(@PathVariable String flag, @RequestParam(required = false) String play, HttpServletResponse response) {
        OutputStream os;
        List<String> fileNames = FileUtil.listFileNames(BASE_FILE_PATH);
        String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse(""); //  System.currentTimeMillis() + originalFilename
        try {
            if (StrUtil.isNotEmpty(fileName)) {
                String realName = fileName.substring(fileName.indexOf("_") + 1);
                if ("1".equals(play)) {
                    response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(realName, "UTF-8"));
                } else {
                    response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realName, "UTF-8"));
                }
                byte[] bytes = FileUtil.readBytes(BASE_FILE_PATH + fileName);
                os = response.getOutputStream();
                os.write(bytes);
                os.flush();
                os.close();
            }
        } catch (Exception e) {
            log.error("文件下載失敗", e);
        }
    }

文件上傳接口

1.接口設(shè)置

  • @postMapping(“file/upload”):這個(gè)注解表明這個(gè)方法處理HTTP POST請(qǐng)求,請(qǐng)求路徑是/file/upload。
  • Public Result uploadFile(Multipartfile file):Result是一個(gè)自定義的響應(yīng)對(duì)象,包含了操作成功或操作失敗的狀態(tài),以及相關(guān)數(shù)據(jù)。

2.文件處理

  • String originalFilename = file.getOriginalFilename():獲取上傳文件的原始文件名。
  • if (StrUtil.isBlank(originalFilename)):檢查文件名是否為空,如果為空,返回錯(cuò)誤響應(yīng)(Result.error)。
  • long flag = System.currentTimeMillis():獲取當(dāng)前時(shí)間戳(毫秒),用于創(chuàng)建唯一的文件名。
  • String filePath = BASE_FILE_PATH + flag + "_" + originalFilename:構(gòu)建完整的文件保存路徑。BASE_FILE_PATH指存儲(chǔ)文件的根目錄,文件名由時(shí)間戳和原始文件名拼接而成。

3.文件保存

  • FileUtil.mkParentDirs(filePath):確保所有父目錄都存在,如果不存在,則創(chuàng)建它們。
  • file.transferTo(FileUtil.file(filePath)):這行關(guān)鍵代碼將上傳的文件內(nèi)容保存到服務(wù)器上的filePath路徑。

4.令牌生成(可選)

  • Admin currentAdmin = TokenUtils.getCurrentAdmin():獲取當(dāng)前登錄的管理員用戶,這意味著實(shí)現(xiàn)了身份驗(yàn)證。
  • String token = TokenUtils.genToken(currentAdmin.getId().toString(), currentAdmin.getPassword(), 15):根據(jù)管理員ID、密碼和15分鐘的過期時(shí)間生成一個(gè)jwt令牌。

5.URL構(gòu)建

  • String url = "http://localhost:9090/api/book/file/download/" + flag + "?&token=" + token:構(gòu)建一個(gè)指向下載接口(/api/book/file/download/)的URL,包含時(shí)間戳(flag)和生成的令牌。
  • if(originalFilename.endsWith("png")||originalFilename.endsWith("jpg") || originalFilename.endsWith("pdf")):如果是圖片(png、jpg)或pdf文件,則在URL后面添加&play=1,這表示服務(wù)器可能提供文件預(yù)覽功能。

6.響應(yīng)

  • return Result.success(url):上傳成功后,返回包含下載的Result.success(url)響應(yīng)
  • catch (Exception e):處理過程中可能出現(xiàn)的異常,記錄錯(cuò)誤日志并返回一個(gè)通用的Result.error響應(yīng)。

文件下載接口

1.注解

  • (1)@GetMapping("/file/download/{flag}"):使用GetingMapping注解處理Get請(qǐng)求,路徑包含一個(gè)變量{flag},將被捕獲并傳遞給方法。
  • (2)@PathVariable String flag:此注解將{flag}路徑變量的值綁定到方法的flag參數(shù)。
  • (3)@RequestParam(required = false) String play:此注解將可選查詢參數(shù)”play”的值綁定到方法的play參數(shù)。required=false使此參數(shù)成為可選參數(shù)。

2.方法參數(shù):

  • (1)String flag:此參數(shù)將包含作為URL中{flag}傳遞的值。它用于標(biāo)識(shí)要下載的文件。
  • (2)String play:此可選參數(shù)(來自查詢字符串)可用于控制下載行為。如果其值為“1”,則文件可能會(huì)直接在瀏覽器中打開(內(nèi)聯(lián))。否則,它將被視為常規(guī)下載。
  • (3)HttpServletResponse response:此對(duì)象用于操作發(fā)送回客戶端的HTTP響應(yīng)。

3.文件處理

  • (1)List<String> fileNames = FileUtil.listFileNames(BASE_FILE_PATH):此行假設(shè)存在一個(gè)FileUtil類,其中包含一個(gè)listFileNames方法,該方法從BASE_FILE_PATH指定的目錄中檢索文件名列表。
  • (2)String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse(""):此行使用Java流查找包含提供的flag的文件名。
  • (3)String realName = fileName.substring(fileName.indexOf("_") + 1):通過刪除找到的文件名中的任何前綴(第一個(gè)”_”之前)來提取實(shí)際文件名。

響應(yīng)處理

if ("1".equals(play)) {

                    response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(realName, "UTF-8"));

                } else {

                    response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realName, "UTF-8"));

                }

檢查play參數(shù)的值。如果play為“1”,則將Content-Disposition標(biāo)頭設(shè)置為"inline;filename=" + URLEncoder.encode(realName, "UTF-8"),這通常告訴瀏覽器嘗試直接打開文件。否則,他會(huì)將標(biāo)頭設(shè)置為 "attachment;filename=" + URLEncoder.encode(realName, "UTF-8"),這通常會(huì)強(qiáng)制瀏覽器下載文件。

  • URLEncoder.encode(realName, "UTF-8")使用UTF-8編碼對(duì)文件名進(jìn)行編碼,以正確處理文件名中的特殊字符和空格。
  • byte[] bytes = FileUtil.readBytes(BASE_FILE_PATH + fileName);使用FileUtil類中的另一個(gè)假設(shè)方法將文件內(nèi)容讀入字節(jié)數(shù)組。
  • os = response.getOutputStream():從response對(duì)象獲取輸出流,允許代碼將數(shù)據(jù)直接寫入HTTP響應(yīng)體。
  • os.write(bytes);os.flush(); os.close();:將文件內(nèi)容(字節(jié)數(shù)組)寫入輸出流,刷新流以確保發(fā)送所有數(shù)據(jù),然后關(guān)閉流。
  • catch (Exception e) { log.error("文件下載失敗", e);}:此catch塊捕獲在文件下載過程中拋出的任何異常,并記錄錯(cuò)誤消息。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)

    Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)

    這篇文章主要給大家介紹了關(guān)于Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)方法,最近項(xiàng)目中需要實(shí)現(xiàn)將文件先存放到ftp上,需要的時(shí)候再?gòu)膄tp上下載,做的過程中碰到了問題,所以這里總結(jié)下,需要的朋友可以參考下
    2023-08-08
  • java工廠實(shí)例BeanFactoryPostProcessor和BeanPostProcessor區(qū)別分析

    java工廠實(shí)例BeanFactoryPostProcessor和BeanPostProcessor區(qū)別分析

    這篇文章主要為大家介紹了BeanFactoryPostProcessor和BeanPostProcessor區(qū)別示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Java中實(shí)現(xiàn)WebSocket方法詳解

    Java中實(shí)現(xiàn)WebSocket方法詳解

    這篇文章主要介紹了Java中實(shí)現(xiàn)WebSocket方法詳解,WebSocket?是一種新型的網(wǎng)絡(luò)協(xié)議,它允許客戶端和服務(wù)器之間進(jìn)行雙向通信,可以實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)交互,需要的朋友可以參考下
    2023-07-07
  • Java 代碼檢查工具之PMD入門使用詳細(xì)教程

    Java 代碼檢查工具之PMD入門使用詳細(xì)教程

    這篇文章主要介紹了Java 代碼檢查工具之PMD入門使用詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot如何利用Twilio?Verify發(fā)送驗(yàn)證碼短信

    SpringBoot如何利用Twilio?Verify發(fā)送驗(yàn)證碼短信

    Twilio提供了一個(gè)名為?Twilio?Verify?的服務(wù),專門用于處理驗(yàn)證碼的發(fā)送和驗(yàn)證,下面我們就來看看如何使用Twilio?Verify實(shí)現(xiàn)發(fā)送驗(yàn)證碼短信吧
    2025-03-03
  • Java代碼實(shí)現(xiàn)哈希表(google 公司的上機(jī)題)

    Java代碼實(shí)現(xiàn)哈希表(google 公司的上機(jī)題)

    這篇文章主要介紹了Java 哈希表詳解(google 公司的上機(jī)題),本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理

    SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理

    FastDFS是一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),它對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問題,本文介紹了SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理,需要的朋友可以參考下
    2024-08-08
  • Spring Boot搭建文件上傳服務(wù)的方法

    Spring Boot搭建文件上傳服務(wù)的方法

    這篇文章主要為大家詳細(xì)介紹了Spring Boot搭建文件上傳服務(wù)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • MyBatis-Plus 與Druid 數(shù)據(jù)源操作

    MyBatis-Plus 與Druid 數(shù)據(jù)源操作

    SpringBoot框架集成MyBatis-Plus和Druid數(shù)據(jù)源,簡(jiǎn)化了數(shù)據(jù)操作與監(jiān)控,MyBatis-Plus作為MyBatis的增強(qiáng)工具,自動(dòng)實(shí)現(xiàn)CRUD操作,減少手寫SQL,提供分頁(yè)、邏輯刪除等功能,本文介紹MyBatis-Plus & Druid 數(shù)據(jù)源總結(jié),感興趣的朋友一起看看吧
    2024-09-09
  • MyBatisPlus利用Service實(shí)現(xiàn)獲取數(shù)據(jù)列表

    MyBatisPlus利用Service實(shí)現(xiàn)獲取數(shù)據(jù)列表

    這篇文章主要為大家詳細(xì)介紹了怎樣使用 IServer 提供的 list 方法查詢多條數(shù)據(jù),這些方法將根據(jù)查詢條件獲取多條數(shù)據(jù),感興趣的可以了解一下
    2022-06-06

最新評(píng)論