使用 React 前端将 Multipart 文件发送到 Spring Boot 后端时如何解决 415 响应

问题描述 投票:0回答:1

我正在使用带有 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
表中。

我不知道从这里该去哪里,因为我找到的所有解决方案现在都在创建错误循环。一种解决方案会导致另一个问题,而该解决方案最终又会回到原来的问题。任何建议将不胜感激,我当然很乐意提供我可能遗漏的任何信息。谢谢!

java reactjs spring-boot axios jsx
1个回答
0
投票

经过太多的搜索,我终于找到了解决方案。我的

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
设置为其值。希望这对其他人有帮助

© www.soinside.com 2019 - 2024. All rights reserved.