在 React 中将文件对象更改为普通对象

Change file object to normal object in React

请为张贴图片向我道歉,但不幸的是,我的问题只能通过图片更好地表达。

我正在使用 antd upload 组件上传文件。

当我使用多个上传模式一个一个地上传完文件后,我得到的结果如下图。

文件上传后提交表单时忽略前两个对象。

api 调用的表单数据已像这样发送,(前两个对象的内容为 undefined,但最后一个对象的内容值以二进制形式提供)

简单的工作示例:

上传2个及以上文件后,请注意demo.tsx第28行的console.log(e.fileList);。结果就像,(第一个对象名称为文件,第二个对象名称为普通对象)

我希望两个对象值都采用与对象相同的格式。请问为什么文件上传后,最后一个是普通对象,而其他以前上传的是文件对象?

如果我上传三个文件,那么我必须调用三个 api,其中有效载荷如下,

第一个文件的负载 api 调用 https://i.stack.imgur.com/s23in.png

第二次 api 调用的负载 https://i.stack.imgur.com/ZHnKT.png

第三次 api 调用的负载 https://i.stack.imgur.com/eqYSd.png

所以只有最后一个有效载荷的内容是二进制的,而其他两个是未定义的,这会阻止图像上传。

您正在发送一个文件对象。您需要使用 FormData 发送文件。它允许您设置 key/value 对。我创建了一个包含完整表单提交的小示例。另附上一些截图。

import { useState, useMemo } from 'react';
import { Upload, Button, message, Form, Input } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { UploadFile } from 'antd/lib/upload/interface';
import { RcFile } from 'rc-upload/lib/interface';
import { POST } from '../../../utils/https';
import axios from 'axios';

interface FormRule {
    title: string;
    attachment?: { file: RcFile; fileList: RcFile[] };
}

const Uploader = () => {
    const [fileList, setFileList] = useState<UploadFile<any>[]>([]);
    const [form] = Form.useForm<FormRule>();

    const validateFileType = ({ type, name }: UploadFile, allowedTypes: string[] = ['image/png', 'image/jpeg']) => {
        return allowedTypes.includes(type!);
    };

    const uploadProps = useMemo(
        () => ({
            multiple: true,
            beforeUpload: (file: UploadFile) => {
                const isAllowedType = validateFileType(file);
                if (!isAllowedType) {
                    message.error(`${file.name} is not PNG file`);
                    return false;
                }
                setFileList((prev) => [...prev, file]);
                return false;
            },
            onRemove: (file: UploadFile) => {
                setFileList((prev) => prev.filter((item) => item.uid !== file.uid));
            }
        }),
        []
    );

    const onSubmit = async (data: FormRule) => {
        // You cannot send files like normal data. You need to convert it into buffer...
        // Use FormData and attach everything you want to send to send to backend
        // If you are using node.js, use multer or any other package of your choice to get all files
        // and get Files from req.files and data from req.body
        let formData = new FormData();
        formData.append('title', data.title);

        // Don't get attachment files from data, use fileList State because
        // it you use attachment from data, it will have all the files that
        // should be not accepted. For example, upload one png file and 1 file other than png or jpeg i.e. txt,
        // it will have txt file + png file.
        if (!!fileList.length) {
            for (const item of fileList) {
                formData.append('attachment', new Blob([item as any]));
            }
        }

        // await axios('..', { data: formData, method: 'POST' });
    };

    return (
        <Form form={form} onFinish={onSubmit} layout='vertical'>
            <Form.Item label='Title' name='title' rules={[{ required: true }]}>
                <Input />
            </Form.Item>
            <Form.Item name='attachment' rules={[{ required: true }]}>
                <Upload {...uploadProps} fileList={fileList}>
                    <Button icon={<UploadOutlined />}>Upload png only</Button>
                </Upload>
            </Form.Item>

            <Button type='primary' htmlType='submit'>
                Submit
            </Button>
        </Form>
    );
};

export default Uploader;