帮我用springboot写一个项目,需求是:1.用户点击按钮上传excel文件,2.把excel文件存到数据库,3.把excel其中的一些数据进行修改和删除,4.excel文件支持多行表头,5.最后输出修改后的excel文件,给我看看各代码的结构还有详细代码
时间: 2024-02-12 16:05:03 浏览: 135
好的,我可以帮你实现这个需求。首先我们需要创建一个Spring Boot项目,可以使用Spring Initializr快速创建一个基础项目。
项目结构:
```
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── controller
│ │ │ │ └── ExcelController.java
│ │ │ ├── model
│ │ │ │ └── ExcelData.java
│ │ │ ├── repository
│ │ │ │ └── ExcelDataRepository.java
│ │ │ ├── service
│ │ │ │ ├── ExcelDataService.java
│ │ │ │ └── ExcelDataServiceImpl.java
│ │ │ └── utils
│ │ │ ├── ExcelUtils.java
│ │ │ ├── FileStorageException.java
│ │ │ └── FileStorageProperties.java
│ │ ├── resources
│ │ │ ├── static
│ │ │ │ └── index.html
│ │ │ ├── templates
│ │ │ └── application.properties
│ │ └── resources
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
└── pom.xml
```
接下来我们先来看一下代码实现:
1. ExcelController.java
该类为控制器类,主要用于接收前端的请求并返回相应的结果。
```java
@RestController
public class ExcelController {
@Autowired
private ExcelDataService excelDataService;
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
try {
excelDataService.store(file);
return ResponseEntity.status(HttpStatus.OK).body("File uploaded successfully!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("Fail to upload file!");
}
}
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile() {
String filename = "output.xlsx";
Resource resource = excelDataService.loadFileAsResource(filename);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
@PostMapping("/modify")
public ResponseEntity<String> modifyData(@RequestBody List<ExcelData> dataList) {
try {
excelDataService.modifyData(dataList);
return ResponseEntity.status(HttpStatus.OK).body("Data modified successfully!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("Fail to modify data!");
}
}
}
```
2. ExcelDataService.java / ExcelDataServiceImpl.java
该类为服务类,主要用于处理上传/下载/修改文件的相关操作。
```java
public interface ExcelDataService {
void store(MultipartFile file);
Resource loadFileAsResource(String filename);
void modifyData(List<ExcelData> dataList);
}
@Service
public class ExcelDataServiceImpl implements ExcelDataService {
private final Path fileStorageLocation;
private final ExcelDataRepository excelDataRepository;
@Autowired
public ExcelDataServiceImpl(FileStorageProperties fileStorageProperties, ExcelDataRepository excelDataRepository) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
this.excelDataRepository = excelDataRepository;
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
@Override
public void store(MultipartFile file) {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
if (fileName.contains("..")) {
throw new FileStorageException("Filename contains invalid path sequence " + fileName);
}
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
List<ExcelData> dataList = ExcelUtils.readExcel(targetLocation.toFile());
excelDataRepository.saveAll(dataList);
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
@Override
public Resource loadFileAsResource(String filename) {
try {
Path filePath = this.fileStorageLocation.resolve(filename).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return resource;
} else {
throw new FileStorageException("File not found " + filename);
}
} catch (MalformedURLException ex) {
throw new FileStorageException("File not found " + filename, ex);
}
}
@Override
public void modifyData(List<ExcelData> dataList) {
for (ExcelData data : dataList) {
Optional<ExcelData> existingData = excelDataRepository.findById(data.getId());
if (existingData.isPresent()) {
ExcelData newData = existingData.get();
newData.setName(data.getName());
newData.setAge(data.getAge());
excelDataRepository.save(newData);
}
}
Path targetLocation = this.fileStorageLocation.resolve("output.xlsx");
ExcelUtils.writeExcel(targetLocation.toFile(), excelDataRepository.findAll());
}
}
```
3. ExcelData.java
该类为数据模型类,对应数据库中的一张表。
```java
@Entity
@Table(name = "excel_data")
public class ExcelData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
// getter and setter methods
}
```
4. ExcelDataRepository.java
该类为数据仓库类,用于操作数据库中的数据。
```java
@Repository
public interface ExcelDataRepository extends JpaRepository<ExcelData, Long> {
}
```
5. ExcelUtils.java
该类为工具类,主要用于读写Excel文件。
```java
public class ExcelUtils {
public static List<ExcelData> readExcel(File file) {
List<ExcelData> dataList = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(file)) {
Workbook workbook = WorkbookFactory.create(fis);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
boolean hasHeader = true;
String[] headers = null;
while (iterator.hasNext()) {
Row currentRow = iterator.next();
if (hasHeader) {
headers = readHeaders(currentRow);
hasHeader = false;
} else {
ExcelData data = new ExcelData();
for (int i = 0; i < headers.length; i++) {
String header = headers[i];
Cell cell = currentRow.getCell(i);
if (cell != null) {
switch (header) {
case "Name":
data.setName(cell.getStringCellValue());
break;
case "Age":
data.setAge((int) cell.getNumericCellValue());
break;
}
}
}
if (data.getName() != null && data.getAge() != null) {
dataList.add(data);
}
}
}
} catch (IOException | InvalidFormatException e) {
e.printStackTrace();
}
return dataList;
}
private static String[] readHeaders(Row row) {
List<String> headers = new ArrayList<>();
Iterator<Cell> cellIterator = row.iterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
headers.add(cell.getStringCellValue());
}
return headers.toArray(new String[0]);
}
public static void writeExcel(File file, List<ExcelData> dataList) {
try (FileOutputStream fos = new FileOutputStream(file)) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
int rowIndex = 0;
Row headerRow = sheet.createRow(rowIndex++);
headerRow.createCell(0).setCellValue("Name");
headerRow.createCell(1).setCellValue("Age");
for (ExcelData data : dataList) {
Row row = sheet.createRow(rowIndex++);
row.createCell(0).setCellValue(data.getName());
row.createCell(1).setCellValue(data.getAge());
}
workbook.write(fos);
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
6. FileStorageException.java / FileStorageProperties.java
该类为异常类和配置类,用于处理文件上传下载时的异常和配置文件上传下载的路径。
```java
public class FileStorageException extends RuntimeException {
public FileStorageException(String message) {
super(message);
}
public FileStorageException(String message, Throwable cause) {
super(message, cause);
}
}
@Configuration
@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
}
```
最后,我们需要在application.properties文件中添加以下配置:
```
file.upload-dir=/path/to/uploaded/files
```
这个路径指的是上传的文件存储的路径,可以根据实际情况进行修改。
好了,以上就是实现这个需求的全部代码。需要注意的是,这里只提供了一个基础的实现,实际应用中可能还需要对文件进行校验、处理异常等操作。
阅读全文