webflux环境下上传excel文件,使用POI解析上传的文件时报错:java.io.IOException: Unable to read entire header; 0 bytes read; expected 512 bytes
报错代码:
@PostMapping(value = "read/excel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> uploadFile(
@ApiParam(value = "excel文件(xls,xlsx)", required = true) @RequestPart("file") FilePart filePart) {
Path tempPath = null;
try {
//写入缓存文件中
tempPath = Files.createTempFile("tempFile", filePart.filename());
File file = tempPath.toFile();
filePart.transferTo(file);
//使用POI解析excel文件
parseFileUsePOI(file);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
//使用后删除
FilePartUtils.deleteQuietly(tempPath);
}
return ResponseEntity.ok().build();
}
错误原因:
文件上传后查看生成的临时文件,发现文件大小总是0k,打开后没有数据,应该FilePart没有写入到缓存文件中,文件始终为空,故POI在读取该文件检查前512byte肯定是没有数据的,故报错。
解决方法:
@PostMapping(value = "read/excel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> uploadFile(
@ApiParam(value = "excel文件(xls,xlsx)", required = true) @RequestPart("file") FilePart filePart) {
Path tempPath = null;
try {
//写入缓存文件中
tempPath = Files.createTempFile("tempFile", filePart.filename());
Path fileName = tempPath.getFileName();
//===》此处是关键《===
DataBufferUtils.write(filePart.content(), AsynchronousFileChannel.open(tempPath, StandardOpenOption.WRITE), 0)
.doOnComplete(() -> {
log.info("File saved to server location : " + fileName);
}).subscribe();
//使用POI解析excel文件
parseFileUsePOI(tempPath.toFile());
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
//使用后删除
FilePartUtils.deleteQuietly(tempPath);
}
return ResponseEntity.ok().build();
}
附一个简单工具类:
import java.io.File;
import java.io.IOException;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.codec.multipart.FilePart;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FilePartUtils {
public static File writeTempFile(FilePart filePart) throws IOException {
return writeTempPath(filePart).toFile();
}
public static Path writeTempPath(FilePart filePart) throws IOException {
Path path = Files.createTempFile("tempFile", filePart.filename());
Path fileName = path.getFileName();
DataBufferUtils.write(filePart.content(), AsynchronousFileChannel.open(path, StandardOpenOption.WRITE), 0)
.doOnComplete(() -> {
log.info("File saved to server location : " + fileName);
}).subscribe();
return path;
}
public static File writeFile(FilePart filePart, String parentPath) throws IOException {
return writePath(filePart, parentPath).toFile();
}
public static File writeFile(FilePart filePart, String parentPath, String newFilename) throws IOException {
return writePath(filePart, parentPath, newFilename).toFile();
}
public static Path writePath(FilePart filePart, String parentPath) throws IOException {
return writePath(filePart, parentPath, null);
}
public static Path writePath(FilePart filePart, String parentPath, String newFilename) throws IOException {
Path path = Files
.createFile(Paths.get(parentPath, StringUtils.defaultIfEmpty(newFilename, filePart.filename())));
Path fileName = path.getFileName();
DataBufferUtils.write(filePart.content(), AsynchronousFileChannel.open(path, StandardOpenOption.WRITE), 0)
.doOnComplete(() -> {
log.info("File saved to server location : " + fileName);
}).subscribe();
return path;
}
public static void deleteQuietly(Path path) {
if (path != null) {
try {
Files.deleteIfExists(path);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
public static void deleteQuietly(File file) {
if (file != null) {
try {
file.deleteOnExit();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}