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

使用Spring?Boot快速構(gòu)建一個(gè)簡單的文件處理工具

 更新時(shí)間:2025年06月03日 08:56:43   作者:碼農(nóng)阿豪@新空間  
在現(xiàn)代Web應(yīng)用中,文件上傳與處理是常見的需求,本文將通過一個(gè)實(shí)際案例,詳細(xì)介紹如何使用Spring?Boot構(gòu)建一個(gè)文件處理工具,感興趣的小伙伴可以參考一下

引言

在現(xiàn)代Web應(yīng)用中,文件上傳與處理是常見的需求。本文將通過一個(gè)實(shí)際案例,詳細(xì)介紹如何使用Spring Boot構(gòu)建一個(gè)文件處理工具,實(shí)現(xiàn)以下功能:

  • 接收用戶上傳的ZIP壓縮包
  • 解壓ZIP文件并提取其中的圖片
  • 使用OCR技術(shù)識(shí)別圖片中的關(guān)鍵信息
  • 將識(shí)別結(jié)果導(dǎo)出為Excel文件
  • 同時(shí)保存結(jié)果到服務(wù)器本地

我們將從項(xiàng)目搭建、核心功能實(shí)現(xiàn)到錯(cuò)誤處理等方面進(jìn)行全面講解,并提供完整的代碼示例。

一、項(xiàng)目概述與搭建

1.1 功能需求

用戶通過網(wǎng)頁上傳ZIP文件

后端解壓ZIP,提取圖片文件

對(duì)每張圖片進(jìn)行OCR識(shí)別(如快遞單號(hào)、手機(jī)號(hào))

將識(shí)別結(jié)果生成Excel并提供下載

在服務(wù)器resources/output目錄保留結(jié)果副本

1.2 技術(shù)棧

后端:Spring Boot 2.7+

模板引擎:Thymeleaf(前后端不分離)

文件處理:Apache Commons Compress(ZIP解壓)

OCR識(shí)別:百度OCR API(或其他OCR服務(wù))

Excel操作:Apache POI

1.3 初始化項(xiàng)目

使用Spring Initializr創(chuàng)建項(xiàng)目,添加依賴:

<dependencies>
    <!-- Web支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- 模板引擎 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <!-- Excel操作 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    
    <!-- 文件上傳 -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>

二、核心功能實(shí)現(xiàn)

2.1 文件上傳接口

2.2 ZIP解壓實(shí)現(xiàn)

private List<File> unzipFile(MultipartFile file) throws IOException {
    List<File> extractedFiles = new ArrayList<>();
    Path tempDir = Files.createTempDirectory("unzip_");
    
    try (ZipInputStream zipIn = new ZipInputStream(file.getInputStream())) {
        ZipEntry entry;
        while ((entry = zipIn.getNextEntry()) != null) {
            Path filePath = tempDir.resolve(entry.getName());
            
            // 防止ZIP滑動(dòng)攻擊
            if (!filePath.normalize().startsWith(tempDir)) {
                throw new SecurityException("非法文件路徑");
            }
            
            if (!entry.isDirectory() && isImageFile(entry.getName())) {
                Files.copy(zipIn, filePath);
                extractedFiles.add(filePath.toFile());
            }
            zipIn.closeEntry();
        }
    }
    return extractedFiles;
}
???????private boolean isImageFile(String filename) {
    String[] extensions = {".jpg", ".png", ".jpeg"};
    return Arrays.stream(extensions).anyMatch(filename::endsWith);
}

2.3 OCR信息識(shí)別

public OrderInfo getPicInfo(String imagePath) {
    OrderInfo info = new OrderInfo();
    try {
        String base64Image = imageToBase64(imagePath);
        String ocrResult = callOcrApi(base64Image); // 調(diào)用OCR API
        info.setExpressNumber(extractExpressNo(ocrResult));
        info.setPhoneNumber(extractPhoneNo(ocrResult));
    } catch (Exception e) {
        info.setError(true);
    }
    return info;
}

2.4 生成Excel并保存

private void saveToResourcesOutput(Workbook workbook) throws IOException {
    Path outputDir = Paths.get("src/main/resources/output");
    if (!Files.exists(outputDir)) {
        Files.createDirectories(outputDir);
    }
    
    String filename = "result_" + System.currentTimeMillis() + ".xlsx";
    try (FileOutputStream out = new FileOutputStream(outputDir.resolve(filename).toFile())) {
        workbook.write(out);
    }
}

三、前端頁面實(shí)現(xiàn)

Thymeleaf模板(index.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>圖片處理工具</title>
</head>
<body>
    <h1>上傳ZIP壓縮包</h1>
    <form method="post" action="/upload" enctype="multipart/form-data">
        <input type="file" name="file" accept=".zip" required>
        <button type="submit">提交</button>
    </form>
    
    <div th:if="${message}" th:text="${message}"></div>
</body>
</html>

四、錯(cuò)誤處理與優(yōu)化

4.1 常見錯(cuò)誤解決

問題1:Thymeleaf模板找不到

Error resolving template [index], template might not exist

解決方案:

  • 確認(rèn)index.html位于resources/templates/目錄
  • 檢查是否添加了Thymeleaf依賴
  • 確??刂破鞣祷氐囊晥D名稱匹配

問題2:ZIP解壓失敗

增強(qiáng)健壯性:

try {
    unzipFile(file);
} catch (IOException e) {
    log.error("解壓失敗", e);
    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "無效的ZIP文件");
}

4.2 性能優(yōu)化建議

大文件處理:使用SXSSFWorkbook流式寫入Excel

并發(fā)處理:對(duì)多圖片采用線程池并行OCR識(shí)別

臨時(shí)文件清理:

@Scheduled(fixedRate = 86400000) // 每天清理
public void cleanTempFiles() {
    // 刪除超過1天的臨時(shí)文件
}

五、問題分析與解決方案

問題描述

用戶在使用Spring Boot開發(fā)一個(gè)文件處理應(yīng)用時(shí),遇到以下兩個(gè)主要問題:

  • 中文文件名處理失?。荷蟼靼形奈募腪IP文件時(shí),報(bào)錯(cuò)MALFORMED。
  • JAR包無法運(yùn)行:使用java -jar啟動(dòng)時(shí)提示no main manifest attribute,手動(dòng)指定主類后,又報(bào)NoClassDefFoundError。

環(huán)境信息

Spring Boot版本:2.6.13

JDK版本:1.8

構(gòu)建工具:Maven

問題場景:文件上傳解析 + 生成Excel

問題分析

1.中文文件名處理失?。∕ALFORMED錯(cuò)誤)

問題原因

  • 在解壓ZIP文件時(shí),ZipInputStream默認(rèn)使用的編碼可能與ZIP文件的實(shí)際編碼不一致,導(dǎo)致中文文件名解析錯(cuò)誤。
  • 路徑安全檢查不完善,可能引發(fā)安全漏洞(如ZIP路徑遍歷攻擊)。

解決方案

優(yōu)化unzipFile方法,正確處理編碼和路徑安全:

private List<File> unzipFile(MultipartFile file) throws IOException {
    List<File> extractedFiles = new ArrayList<>();
    File tempDir = Files.createTempDirectory("unzip_").toFile();
    tempDir.deleteOnExit();

    // 嘗試GBK編碼(常見于Windows生成的ZIP)
    try (ZipInputStream zipIn = new ZipInputStream(file.getInputStream(), Charset.forName("GBK"))) {
        ZipEntry entry;
        while ((entry = zipIn.getNextEntry()) != null) {
            String entryName = entry.getName();
            File destFile = new File(tempDir, entryName);
            
            // 安全檢查:防止ZIP路徑遍歷
            String canonicalPath = destFile.getCanonicalPath();
            if (!canonicalPath.startsWith(tempDir.getCanonicalPath() + File.separator)) {
                throw new SecurityException("ZIP文件包含非法路徑: " + entryName);
            }

            if (!entry.isDirectory() && isImageFile(entryName)) {
                Files.createDirectories(destFile.getParentFile().toPath());
                Files.copy(zipIn, destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                extractedFiles.add(destFile);
            }
            zipIn.closeEntry();
        }
    } catch (Exception e) {
        // 如果GBK失敗,回退到UTF-8
        try (ZipInputStream zipIn = new ZipInputStream(file.getInputStream(), StandardCharsets.UTF_8)) {
            // 重復(fù)解壓邏輯...
        }
    }
    return extractedFiles;
}

關(guān)鍵改進(jìn)點(diǎn)

多編碼支持:優(yōu)先嘗試GBK(常見中文編碼),失敗后回退到UTF-8。

路徑安全:使用getCanonicalPath檢查路徑合法性,防止惡意ZIP文件攻擊。

代碼健壯性:使用Files.copy替代手動(dòng)緩沖讀寫,更高效可靠。

2.JAR包無法運(yùn)行(NoClassDefFoundError)

問題原因

打包時(shí)未正確生成可執(zhí)行的Spring Boot JAR,導(dǎo)致:

  • 缺少M(fèi)ANIFEST.MF中的Main-Class。
  • 依賴庫未打包進(jìn)JAR(BOOT-INF/lib缺失)。

解決方案

修正pom.xml,確保正確打包:

<build>
    <plugins>
        <!-- 1. 指定Java編譯版本 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>

        <!-- 2. 關(guān)鍵:正確配置Spring Boot Maven插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal> <!-- 生成可執(zhí)行JAR -->
                    </goals>
                </execution>
            </executions>
            <configuration>
                <mainClass>com.debang.debang_phone_tool.DebangPhoneToolApplication</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

關(guān)鍵改進(jìn)點(diǎn)

移除<skip>true</skip>:確保插件執(zhí)行重新打包操作。

明確指定mainClass:避免運(yùn)行時(shí)找不到主類。

驗(yàn)證打包結(jié)果

# 檢查JAR結(jié)構(gòu)
jar tf target/debang_phone_tool-0.0.1-SNAPSHOT.jar | grep BOOT-INF/lib
# 檢查MANIFEST.MF
jar xf target/debang_phone_tool-0.0.1-SNAPSHOT.jar META-INF/MANIFEST.MF && cat META-INF/MANIFEST.MF

完整解決方案

修正后的項(xiàng)目結(jié)構(gòu)

src/
├── main/
│   ├── java/
│   │   └── com/debang/debang_phone_tool/
│   │       ├── DebangPhoneToolApplication.java  # Spring Boot主類
│   │       ├── controller/                      # 控制器
│   │       └── service/                         # 業(yè)務(wù)邏輯
│   └── resources/
│       ├── static/                              # 靜態(tài)文件
│       └── application.yml                      # 配置文件
pom.xml                                         # 修正后的Maven配置

打包與運(yùn)行命令

# 清理并重新打包
mvn clean package

# 后臺(tái)運(yùn)行(Linux)
nohup java -jar target/debang_phone_tool-0.0.1-SNAPSHOT.jar > app.log 2>&1 &

# 查看日志
tail -f app.log

總結(jié)

1.編碼問題

文件處理:顯式指定編碼(如GBK/UTF-8),避免依賴平臺(tái)默認(rèn)值。

路徑安全:使用getCanonicalPath檢查路徑合法性。

2.打包問題

必須使用spring-boot-maven-plugin:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

驗(yàn)證JAR結(jié)構(gòu):

  • 確保存在BOOT-INF/lib(依賴庫)和META-INF/MANIFEST.MF。
  • 避免<skip>true</skip>:否則會(huì)導(dǎo)致依賴未打包。

3.日志與監(jiān)控

日志重定向:使用2>&1捕獲所有輸出:

nohup java -jar app.jar > app.log 2>&1 &

進(jìn)程管理:結(jié)合systemd或supervisord實(shí)現(xiàn)服務(wù)化。

六、總結(jié)

本文實(shí)現(xiàn)了一個(gè)完整的Spring Boot文件處理流程,關(guān)鍵點(diǎn)包括:

  • 使用MultipartFile接收上傳文件
  • 安全的ZIP解壓與路徑校驗(yàn)
  • 第三方OCR服務(wù)集成
  • 動(dòng)態(tài)Excel生成與雙存儲(chǔ)(下載+本地保存)
  • 全面的異常處理機(jī)制

擴(kuò)展方向:

  • 添加用戶系統(tǒng),隔離不同用戶的數(shù)據(jù)
  • 支持更多文件格式(如RAR、7z)
  • 集成更強(qiáng)大的OCR引擎(如Tesseract)

GitHub示例:完整代碼可在 https://github.com/example/file-processor 獲取

通過這個(gè)案例,讀者可以掌握Spring Boot中文件處理的核心技術(shù),并快速應(yīng)用到實(shí)際項(xiàng)目中。

以上就是使用Spring Boot快速構(gòu)建一個(gè)簡單的文件處理工具的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot文件處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java?的訪問修飾符public,protected,private(封裝、繼承)

    Java?的訪問修飾符public,protected,private(封裝、繼承)

    這篇文章主要介紹了Java?的訪問修飾符public,protected,private(封裝、繼承),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 最新評(píng)論