Multipart Upload
We will show you how to multipart upload with refine.
Let's start with the creation form
first.
Create Form​
Let's add the image field to the post creation form
.
import {
useApiUrl,
} from "@refinedev/core";
import {
getValueFromEvent,
Create,
useForm,
} from "@refinedev/antd";
import {
Upload,
Form,
Input,
} from "antd";
export const PostCreate: React.FC = () => {
const { formProps, saveButtonProps } = useForm<IPost>();
const apiUrl = useApiUrl();
return (
<Create saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item
label="Title"
name="title"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item label="Image">
<Form.Item
name="image"
valuePropName="fileList"
getValueFromEvent={getValueFromEvent}
noStyle
>
<Upload.Dragger
name="file"
action={`${apiUrl}/media/upload`}
listType="picture"
maxCount={5}
multiple
>
<p className="ant-upload-text">
Drag & drop a file in this area
</p>
</Upload.Dragger>
</Form.Item>
</Form.Item>
</Form>
</Create>
);
};
interface IPost {
id: number;
title: string;
image: [
{
uid: string;
name: string;
url: string;
status: "error" | "success" | "done" | "uploading" | "removed";
},
];
}
We can reach the API URL by using the useApiUrl
hook.
It will look like this.
What we need now is an upload end-point that accepts multipart uploads. We write this address in the action
property of the Upload
component.
{
"file": "binary"
}
This end-point should be Content-type: multipart/form-data
and Form Data: file: binary
?.
This end-point should respond similarly.
{
"url": "https://example.com/uploaded-file.jpeg"
}
We have to use the getValueFromEvent
method to convert the uploaded files to Antd UploadFile object.
This data is sent to the API when the form is submitted.
{
"title": "Test",
"image": [
{
"uid": "rc-upload-1620630541327-7",
"name": "greg-bulla-6RD0mcpY8f8-unsplash.jpg",
"url": "https://refine.ams3.digitaloceanspaces.com/78c82c0b2203e670d77372f4c20fc0e2",
"type": "image/jpeg",
"size": 70922,
"percent": 100,
"status": "done"
}
]
}
The following data are required for the Antd Upload component and all should be saved.
Property | Description |
---|---|
uid | Unique id |
name | File Name |
url | Download URL |
status | error, success, done, uploading, removed |
Edit Form​
Let's add the image field to the post editing form.
import {
useApiUrl,
} from "@refinedev/core";
import {
getValueFromEvent,
Edit,
useForm,
} from "@refinedev/antd";
import {
Upload,
Form,
Input,
} from "antd";
export const PostEdit: React.FC = () => {
const { formProps, saveButtonProps } = useForm<IPost>();
const apiUrl = useApiUrl();
return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item
label="Title"
name="title"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item label="Image">
<Form.Item
name="image"
valuePropName="fileList"
getValueFromEvent={getValueFromEvent}
noStyle
>
<Upload.Dragger
name="file"
action={`${apiUrl}/media/upload`}
listType="picture"
maxCount={5}
multiple
>
<p className="ant-upload-text">
Drag & drop a file in this area
</p>
</Upload.Dragger>
</Form.Item>
</Form.Item>
</Form>
</Edit>
);
};
A request, like the one below, is sent for edit form.
{
"id": 1,
"title": "Test",
"image": [
{
"uid": "rc-upload-1620630541327-7",
"name": "greg-bulla-6RD0mcpY8f8-unsplash.jpg",
"url": "https://refine.ams3.digitaloceanspaces.com/78c82c0b2203e670d77372f4c20fc0e2",
"type": "image/jpeg",
"size": 70922,
"percent": 100,
"status": "done"
}
]
}
This data is sent to the API when form is submitted.
{
"title": "Test",
"image": [
{
"uid": "rc-upload-1620630541327-7",
"name": "greg-bulla-6RD0mcpY8f8-unsplash.jpg",
"url": "https://refine.ams3.digitaloceanspaces.com/78c82c0b2203e670d77372f4c20fc0e2",
"type": "image/jpeg",
"size": 70922,
"percent": 100,
"status": "done"
}
]
}
Uploading State​
You may want to disable the "Save" button in the form while the upload is going on. To do this, you can use the useFileUploadState
hook.
import { useApiUrl } from "@refinedev/core";
import {
getValueFromEvent,
useFileUploadState,
Create,
useForm,
} from "@refinedev/antd";
import { Upload, Form, Input } from "antd";
export const PostCreate: React.FC = () => {
const { formProps, saveButtonProps } = useForm<IPost>();
const { isLoading, onChange } = useFileUploadState();
const apiUrl = useApiUrl();
return (
<Create
saveButtonProps={{
...saveButtonProps,
disabled: isLoading,
}}
>
<Form {...formProps} layout="vertical">
<Form.Item
label="Title"
name="title"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item label="Image">
<Form.Item
name="image"
valuePropName="fileList"
getValueFromEvent={getValueFromEvent}
noStyle
>
<Upload.Dragger
name="file"
action={`${apiUrl}/media/upload`}
listType="picture"
maxCount={5}
multiple
onChange={onChange}
>
<p className="ant-upload-text">
Drag & drop a file in this area
</p>
</Upload.Dragger>
</Form.Item>
</Form.Item>
</Form>
</Create>
);
};
Example​
npm create refine-app@latest -- --example upload-antd-multipart