我正在使用带有 Spring Boot 后端和 axios 的 React 前端。我正在尝试使用 axios 将图像作为
Multipart
文件发送。这是我在 React 组件中发送文件的函数:
const [selectedImage, setSelectedImage] = useState(null);
function handleSubmit(){
axios.defaults.withCredentials = true;
axios.post('http://localhost:8080/api/image/',
selectedImage)
.then(response => {
if(response.status === 200){
console.log(response.data)
// window.location.href = "/user-dash"
} else
console.log("nope")
return Promise.reject("it broke")
})
.catch(error => console.error(error));
}
这是收集图像数据的
.jsx
部分
<div>
<h1>Upload and Display Image</h1>
{selectedImage && (
<div>
<img
alt="profile pic"
width={"250px"}
src={URL.createObjectURL(selectedImage)}
/>
<button onClick={() => handleSubmit()}>Save</button>
<button onClick={() => setSelectedImage(null)}>Remove</button>
</div>
)}
<input
type="file"
name="myImage"
onChange={(event) => {
console.log(event.target.files[0]);
setSelectedImage(event.target.files[0]);
}}
/>
</div>
console.log
按照我的预期输出File
。然后下面的控制器得到它:
@PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> uploadImage(@RequestParam(value = "myImage") MultipartFile file){
String response = imageDataService.uploadImage(file);
return ResponseEntity.status(HttpStatus.OK)
.body(response);
}
然后将其发送到
ImageDataService
,如下所示(请注意,我正在使用 Lombok):
@Service
@AllArgsConstructor
public class ImageDataService {
private ImageDataRepository imageDataRepository;
public String uploadImage(MultipartFile file) {
try {
imageDataRepository.save(ImageData.builder()
.name(file.getOriginalFilename())
.type(file.getContentType())
.imageData(ImageUtil.compressImage(file.getBytes())).build());
} catch (IOException e) {
throw new RuntimeException(e);
}
return "Image uploaded successfully: " +
file.getOriginalFilename();
}
@Transactional
public ImageData getInfoByImageByName(String name) {
Optional<ImageData> dbImage = imageDataRepository.findByName(name);
return ImageData.builder()
.name(dbImage.get().getName())
.type(dbImage.get().getType())
.imageData(ImageUtil.decompressImage(dbImage.get().getImageData())).build();
}
@Transactional
public byte[] getImage(String name) {
Optional<ImageData> dbImage = imageDataRepository.findByName(name);
byte[] image = ImageUtil.decompressImage(dbImage.get().getImageData());
return image;
}
}
最后,
ImageDataRepository
获取它并应该将 ImageData
对象保存在表中。首先,存储库:
public interface ImageDataRepository extends JpaRepository<ImageData, Long> {
Optional<ImageData> findByName(String name);
}
这是
ImageData
课程:
@Entity
@Table(name = "imageData")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ImageData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String type;
@Lob
@Column(name = "imagedata", length = 1000)
private byte[] imageData;
}
我检查了数据库,
image_data
表中没有新行。我没有在服务器中获得堆栈跟踪,但收到 415 响应代码。这向我表明 Content-Type
未正确设置,但是当我指定 Content-type: "multipart/form-data"
时,我收到一条错误消息,指出“请求被拒绝,因为未找到多部分边界”。在寻找该问题的解决方案时,我找到了一个解决方案,该解决方案表示删除内容类型并且边界将自动生成。这不再产生边界问题,但确实产生了 415 问题。接下来,我尝试向 Content-Type
标题添加边界,如下所示:
axios.post('http://localhost:8080/api/image/',
selectedImage,{
headers:{
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu"
}
})
.then(response => {
if(response.status === 200){
console.log(response.data)
// window.location.href = "/user-dash"
} else
console.log("nope")
return Promise.reject("it broke")
})
.catch(error => console.error(error));
这也没有在服务器上产生堆栈跟踪,但我确实在控制台中收到 400 错误,并且没有数据保存到
image_data
表中。
我不知道从这里该去哪里,因为我找到的所有解决方案现在都在创建错误循环。一种解决方案会导致另一个问题,而该解决方案最终又会回到原来的问题。任何建议将不胜感激,我当然很乐意提供我可能遗漏的任何信息。谢谢!
经过太多的搜索,我终于找到了解决方案。我的
ImageDataController
正在寻找一把名为 myImage
作为 RequestParam
的钥匙。相反,我给它的是没有名称的文件。我的控制器找不到它被告知要查找的密钥,因此它什么也没做。
为了修复它,我将
handleSubmit
文件中的 .jsx
函数更改为:
function handleSubmit(){
const upload = {
"myImage": selectedImage //this creates the key that my controller was looking for and sets the value as the image
}
console.log(selectedImage.name)
axios.defaults.withCredentials = true;
axios.post('http://localhost:8080/api/image/',
upload,{
headers:{
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu"
}
})
.then(response => {
console.log(response.status)
if(response.status === 200){
console.log(response.data)
// window.location.href = "/user-dash"
} else
console.log("nope")
return Promise.reject("it broke")
})
.catch(error => console.error(error));
}
注意
upload
变量的创建并将 selectedImage
设置为其值。希望这对其他人有帮助