首页 > 解决方案 > 在单个 Axios POST 请求中发送 FormData 对象和文件

问题描述

我目前有一个 Spring Boot API 控制器方法(如下),它接受一个对象以及一个 MultiPart 文件。我能够通过 Postman 成功发送 POST 请求,但是我现在正在努力使用 Axios 通过我的前端 ReactJS 应用程序发出这个 post 请求。

@PostMapping(
        path = "/upload",
        consumes = {
                MediaType.APPLICATION_JSON_VALUE,
                MediaType.MULTIPART_FORM_DATA_VALUE
        },
        headers = {
                "Content-Type=multipart/form-data"
        }
)
public SoundProfile uploadSoundProfile(Authentication auth,
                               @RequestPart("soundProfileRequest") SoundProfileRequest soundProfileRequest,
                               @RequestPart("audio_file") MultipartFile audio_file){

    return soundProfileService.uploadSoundProfile(auth, soundProfileRequest, audio_file);
}

邮递员 POST 请求: 在此处输入图像描述

以下是我处理对象和文件的服务方法,该方法负责将对象保存到 MySQL 数据库,然后将文件存储在 Amazon S3 存储桶中。

public SoundProfile uploadSoundProfile(Authentication auth, SoundProfileRequest soundProfileRequest, MultipartFile audio_file) {

    if (audio_file.isEmpty()){
        throw new IllegalStateException("no audio file received");
    }


    AppUser current_user = appUserRepository.findByEmail(auth.getName())
            .orElseThrow(
                    () -> new IllegalStateException("User not found")
            );

    Map<String, String> metadata = new HashMap<>();
    metadata.put("Content-Type", audio_file.getContentType());
    metadata.put("Content-Length", String.valueOf(audio_file.getSize()));

    
    String soundPath = UUID.randomUUID().toString();

    SoundProfile soundProfile = new SoundProfile(
            soundPath, // SoundPath = S3 key
            soundProfileRequest.getCaseBrand(),
            soundProfileRequest.getCaseModel(),
            soundProfileRequest.getSwitches(),
            soundProfileRequest.getKeycaps(),
            soundProfileRequest.getStabilizers(),
            soundProfileRequest.getLube(),
            soundProfileRequest.getMods(),
            current_user
    );

    // save sound profile to database
    soundProfileRepository.save(soundProfile);


    String path = String.format("%s/%s", BucketName.KEYBOARD_AUDIO_BUCKET.getBucketName(), current_user.getUserId());
    String filename = String.format("%s-%s", audio_file.getOriginalFilename(), soundPath);

    // Save audio file to s3 bucket
    try {
        fileStore.saveAudio(
                path,
                filename,
                Optional.of(metadata),
                audio_file.getInputStream()
        );
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }

    return soundProfile;
}

我想分别发送 SoundProfileRequest 对象和多部分文件,这意味着我不想将文件附加到 FormData 对象,但我仍然想在单个发布请求中将文件与表单字段一起发送。

例如在我的前端 React 组件中:

export default function UploadSoundProfile() {

const [caseBrand, setCaseBrand] = useState("");
const [caseModel, setCaseModel] = useState("");
const [switches, setSwitches] = useState("");
const [keycaps, setKeycaps] = useState("");
const [lube, setLube] = useState("");
const [stabilizers, setStabilizers] = useState("");
const [mods, setMods] = useState("");

const [selectedFile, setSelectedFile] = useState("");
const history =  useHistory();


const createSoundProfile = (e) => {
    
    e.preventDefault();

    const url = "/sound-profile/upload";
    const formData = new FormData();

    formData.append('caseBrand', caseBrand);
    formData.append('caseModel', caseModel);
    formData.append('switches', switches);
    formData.append('keycaps', keycaps);
    formData.append('lube', lube);
    formData.append('stabilizers', stabilizers);
    formData.append('mods', mods);


    **// SHOULD FILE ALSO BE APPENDED TO FORMDATA OBJECT HERE?**
    formData.append('audio_file', selectedFile);

    const config = {
        headers: {
            "content-type": "multipart/form-data"
        }
    }

    uploadProfileService.createSoundProfile(url, formData, config);

    history.push("/sound-profile/profile");
};

return (
   ...
)

}

有没有办法在不将文件附加到 FormData 对象的情况下使用 Axios 发出 POST 请求,同时仍然发出单个 post 请求?

我不确定如何做到这一点,或者是否可能。我看过其他帖子,其中文件正在 .append() 到 FormData 对象,但我不确定这是否会导致后端出错。

提前感谢您的帮助!

标签: reactjsspring-bootaxiosmultipartform-data

解决方案


推荐阅读