如何使用Spring Boot WebFlux与OpenCSV读取CSV文件?
嘿,我来帮你搞定Spring Boot WebFlux结合OpenCSV读取CSV文件的需求!咱们一步步来完善你的代码,让它能正常解析上传的CSV:
第一步:添加OpenCSV依赖
先把OpenCSV的依赖加到项目里,这是解析CSV的基础:
- Maven(pom.xml):
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> <!-- 建议用最新稳定版 --> </dependency>
- Gradle(build.gradle.kts):
implementation("com.opencsv:opencsv:5.6")
第二步:完善CSV读取逻辑
WebFlux是响应式框架,FilePart.content()返回的是Flux<DataBuffer>,咱们得先把这些零散的缓冲区合并成完整的输入流,再用OpenCSV解析。这里给你两种实用的实现方式:
方式一:映射到数据类(推荐,代码更简洁)
先定义一个和CSV结构匹配的Kotlin数据类,比如假设你的CSV是用户数据(包含id、name、email三列):
import com.opencsv.bean.CsvBindByName data class User( @CsvBindByName(column = "id") val id: Long, @CsvBindByName(column = "name") val name: String, @CsvBindByName(column = "email") val email: String )
然后完善你的Controller方法:
import com.opencsv.bean.CsvToBeanBuilder import org.springframework.http.MediaType import org.springframework.http.codec.multipart.FilePart import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.RestController import reactor.core.publisher.Flux import org.springframework.core.io.buffer.DataBufferUtils import java.io.InputStreamReader import java.nio.charset.Charsets @RestController class CsvUploadController { @PostMapping(value = ["/upload-csv"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) fun uploadCsvFile(@RequestPart("file") filePart: FilePart): Flux<User> { // 合并所有DataBuffer,转换成可读取的输入流 return DataBufferUtils.join(filePart.content()) .map { dataBuffer -> // 指定UTF-8编码避免乱码 InputStreamReader(dataBuffer.asInputStream(), Charsets.UTF_8) } .flatMapMany { reader -> // 用OpenCSV的CsvToBean直接把CSV行映射到User对象 val userList = CsvToBeanBuilder<User>(reader) .withType(User::class.java) .withIgnoreLeadingWhiteSpace(true) // 忽略字段前的空格 .build() .parse() // 把List转成响应式的Flux返回 Flux.fromIterable(userList) } .doFinally { // 确保资源被正确释放 DataBufferUtils.release(filePart.content()) } } }
方式二:手动解析每行(适合不需要实体类的场景)
如果只是想读取原始的CSV行数据,不需要映射到实体,可以用CSVReader手动处理:
import com.opencsv.CSVReader import org.springframework.core.io.buffer.DataBufferUtils import java.io.InputStreamReader // 替换上面Controller里的flatMapMany部分 .flatMapMany { reader -> CSVReader(reader).use { csvReader -> // 跳过第一行表头(如果你的CSV有表头的话) val rows = csvReader.readAll().drop(1) Flux.fromIterable(rows) } }
一些注意事项
- 编码问题:一定要指定正确的文件编码(比如UTF-8),否则容易出现乱码
- 大文件处理:上面的方式会把整个文件加载到内存,如果是超大CSV,建议用流式逐行解析,避免OOM。可以结合
DataBufferUtils.readInputStream()和OpenCSV的流式API实现 - 资源释放:WebFlux的DataBuffer和IO流都要注意释放,代码里的
use块和doFinally已经帮我们处理了大部分场景
内容的提问来源于stack exchange,提问作者Waley
相关产品推荐
相关产品推荐

