在 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;
请为张贴图片向我道歉,但不幸的是,我的问题只能通过图片更好地表达。
我正在使用 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;