我正在尝试使用 cloudinary 解析多部分文件的 url。但出于某种原因,我无法弄清楚为什么 cloudinary url 没有连接到连接到 PostgresSQL 的 Spring Boot 实体。具体来说就是图像栏。我将其归结为可能影响它的四个区域:我的 Cloudinary 配置、我的员工服务类、我的表单控制器和我的索引文件。
这是员工模型:
package com.employee.employee.models;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Employees {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String companyName;
@Column
private String role;
@Column
private String firstName;
@Column
private String lastName;
@Column
private int age;
@Column
private String image;
public Employees(){
}
// public Employees(String companyName, String role, String firstName, String lastName, int age, String image) {
// this.companyName = companyName;
// this.role = role;
// this.firstName = firstName;
// this.lastName = lastName;
// this.age = age;
// this.image = image;
// }
public long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setImage(String image) {
this.image = image;
}
public String getImage() {
return image;
}
}
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css" />
<title>Employee Form</title>
</head>
<body>
<h1>Employee Form</h1>
<form id="employee-form" action="#" th:action="@{/employee}" th:object="${employees}" method="post" enctype="multipart/form-data">
<label for="firstName">First Name</label>
<input type="text" id="firstName" th:field="*{firstName}"name="firstName">
<label for="lastName">Last Name</label>
<input type="text" id="lastName" th:field="*{lastName}" name="lastName">
<label for="companyName">Company Name</label>
<input type="text" id="companyName" th:field="*{companyName}" name="companyName">
<label for="companyRoleName">Company Role</label>
<input type="text" id="companyRoleName" th:field="*{role}" name="role">
<label for="age">Age</label>
<input type="text" id="age" th:field="*{age}" name="age">
<input id="uploadImage" name="image" type="file" class="imageUpload" value="Upload Image">
<input id="submitted" class="submitButton" type="submit" value="Submit">
<button id="resultID" class="resultButton"><a href="/result">Get Card Result!</a></button>
</form>
<script src="submit-script.js"></script>
</body>
</html>
CloudinaryConfig.java:
package com.employee.employee.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.cloudinary.*;
import io.github.cdimascio.dotenv.Dotenv;
@Configuration
public class CloudinaryConfig {
@Bean
public Cloudinary cloudinary(){
Dotenv dotenv = Dotenv.load();
Cloudinary cloudinary = new Cloudinary(dotenv.get("CLOUDINARY_URL"));
cloudinary.config.secure = true;
return cloudinary;
}
}
EmployeeService.java:
package com.employee.employee.service;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.cloudinary.Cloudinary;
import com.employee.employee.models.Employees;
import com.employee.employee.repo.EmployeeRepo;
@Service
public class EmployeeService {
@Autowired
EmployeeRepo employeeRepo;
@Autowired
Cloudinary cloudinary;
public List<Employees> getAllEmployees(){
return employeeRepo.findAll();
}
public void addEmployee(Employees employee){
employeeRepo.save(employee);
}
public String uploadFile(MultipartFile multipartFile) throws IOException {
try{
String res = cloudinary.uploader()
.upload(multipartFile.getBytes(), Map.of("public_id", UUID.randomUUID().toString()))
.get("url")
.toString();
System.out.println(res);
return res;
} catch(Exception e){
System.err.println(e.getMessage());
e.printStackTrace();
}
return null;
}
}
FormController.java:
package com.employee.employee.controller;
import java.util.List;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.employee.employee.EmployeeAddException;
import com.employee.employee.models.Employees;
import com.employee.employee.service.EmployeeService;
@Controller
public class FormController {
@Autowired
EmployeeService employeeService;
@GetMapping("/")
public String getForm(Model model){
model.addAttribute("employees", new Employees());
return "index";
}
@GetMapping("/result")
public String getResult(){
return "result";
}
@GetMapping("/employee-result")
public @ResponseBody List<Employees> employeeResult(){
return employeeService.getAllEmployees();
}
@PostMapping("/employee")
public String employeeSubmit(@ModelAttribute Employees employee,
@RequestParam("image")MultipartFile multipartFile, Model model) throws IOException{
try{
if(employee.getCompanyName().isBlank() || employee.getFirstName().isBlank() || employee.getLastName().isBlank()
|| employee.getRole().isBlank() || employee.getAge() == 0){
throw new EmployeeAddException("Error: Employee can not be added, null value");
}
} catch (EmployeeAddException e){
model.addAttribute("errorMessage", e.getMessage());
return "error";
}
String image = employeeService.uploadFile(multipartFile);
employee.setImage(image);
employeeService.addEmployee(employee);
model.addAttribute("image", image);
return "redirect:/";
}
}
我期望发生的是将图像 url 传递到 PostgresSQL 数据库。以及将图像传递到结果页面。结果页面有一个加载脚本,用于在单击索引页面上的“获取卡片结果”按钮后显示图像和信息。
结果.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css" />
<title>Employee Cards</title>
</head>
<body>
<main id="container">
</main>
<script src="on-load-script.js"></script>
</body>
</html>
on-load-script.js:
function getResult(){
fetch("/employee-result")
.then(data => {
return data.json();
})
.then(employee => {
const employeeList = document.getElementById("container");
employee.forEach(employees => {
//Elememts
const employeeCard = document.createElement("div");
const employeeCompany = document.createElement("p");
const employeeName = document.createElement("p");
const employeeRole = document.createElement("p");
const employeeAge = document.createElement("p");
const employeeImg = document.createElement("img");
//Classes
employeeCard.classList.add("cardContainer");
employeeName.classList.add("bigFont");
//Employee Info
employeeCompany.innerHTML = employees.companyName;
employeeName.innerHTML = employees.firstName + " " + employees.lastName;
employeeRole.innerHTML = employees.role;
employeeAge.innerHTML = "Age: " + employees.age;
employeeImg.src = employees.image;
employeeImg.alt = "Employee Image";
//Employee Card append
employeeCard.append(employeeName, employeeCompany, employeeRole, employeeAge, employeeImg);
employeeList.appendChild(employeeCard);
});
})
.catch(error => {
console.log(error);
});
}
window.addEventListener("load", getResult);
点击“获取卡片结果”按钮后出现的错误:
submit-script.js:11 POST http://localhost:8080/employee 400 (Bad Request)
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.employee.employee.controller.FormController.employeeSubmit(com.employee.employee.models.Employees,org.springframework.web.multipart.MultipartFile,org.springframework.ui.Model) throws java.io.IOException: [Field error in object 'employees' on field 'image': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@1cba99d1]; codes [typeMismatch.employees.image,typeMismatch.image,typeMismatch.java.lang.String,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employees.image,image]; arguments []; default message [image]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'image'; Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'image': no matching editors or conversion strategy found]] ]
错误消息表明将“图像”字段从
StandardMultipartFile
转换为 String
时出现问题。发生这种情况是因为在您的 Employees
模型中,您已将“图像”字段定义为 String
,但在处理文件上传时,它应该是 MultipartFile
类型来处理文件上传本身。
要解决此问题,您需要更新
Employees
模型以接受“图像”字段的 MultipartFile
而不是 String
。以下是修改 Employees
模型的方法:
import org.springframework.web.multipart.MultipartFile;
// ...
@Column
private MultipartFile image;
进行此更改后,您还应该更新表单以将“图像”字段作为文件输入发送。您已经在表单中设置了正确的 enctype (
enctype="multipart/form-data
),这是文件上传所必需的。
表单中输入的文件应如下所示:
<input id="uploadImage" name="image" type="file" class="imageUpload" value="Upload Image">
通过这些更改,您的
employeeSubmit
中的 FormController
方法现在应该可以正确接收图像文件作为 MultipartFile
:
@PostMapping("/employee")
public String employeeSubmit(@ModelAttribute Employees employee, @RequestParam("image") MultipartFile multipartFile, Model model) throws IOException {
try {
// Validation and other logic...
String image = employeeService.uploadFile(multipartFile);
employee.setImage(image);
employeeService.addEmployee(employee);
model.addAttribute("image", image);
return "redirect:/";
} catch (Exception e) {
model.addAttribute("errorMessage", e.getMessage());
return "error";
}
}