Reputation: 560
I want to know how can I properly upload a file using ReactJS to api using NestJS, so far here is what I have done
in API's swagger, here is the post method for file upload
This is the table from PostgreSQL for that entity
The api is created using this crud typeorm @nestjsx/crud-typeorm
And in my ReactJS code, currently I have this page:
const EditBadge = () => {
const { id } = useParams();
const history = useNavigate();
const [data, setData] = useState({
id: "",
badge_name: "",
badge_description: "",
img_icon: "",
});
const [baseImage, setBaseImage] = useState("");
const { badge_name, badge_description, img_icon } = data;
const onInputChange = (e: any) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const onSubmit = async (e: any) => {
e.preventDefault();
await api.patch(`badges/${id}`, data);
history("/badge");
};
const loadData = async () => {
const result = await api.get(`badges/${id}`);
setData(result.data);
};
useEffect(() => {
loadData();
}, []);
const uploadImage = async (e: any) => {
const file = e.target.files[0];
const base64 = await convertBase64(file);
setBaseImage(String(base64));
};
const convertBase64 = (file: any) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
return (
<Container className="create-badge-container">
<Container className="create-badge-content">
<Row>
<Col>
<div className="img-container text-center">
<Image
className="p-2"
src={baseImage}
alt=""
width={198}
height={219}
/>
</div>
</Col>
</Row>
<Row>
<Col>
<Form className="create-badge-form" onSubmit={(e) => onSubmit(e)}>
<Row className="pt-4">
<Col className="col-4">
<input
type="text"
className="form-control"
placeholder="Badge Name"
aria-label="Badge Name"
name="badge_name"
value={badge_name}
onChange={(e) => onInputChange(e)}
/>
</Col>
<Col className="col-4">
<input
className="form-control"
type="file"
id="file"
accept=".jpeg, .png, .jpg"
name="img_icon"
onChange={(e) => {
uploadImage(e);
}}
/>
</Col>
</Row>
<Row className="pt-4">
<Col className="col-8">
<textarea
className="form-control"
id="exampleFormControlTextarea1"
placeholder="Description"
rows={3}
name="badge_description"
value={badge_description}
onChange={(e) => onInputChange(e)}
></textarea>
</Col>
</Row>
<Row className="pt-5">
<Col className="col-4">
<Button type="submit" className="btn-create">
Update
</Button>
</Col>
</Row>
</Form>
</Col>
</Row>
</Container>
</Container>
);
};
export default EditBadge;
So far this is what I've got base on research, and I got stuck and have no idea how can I post/create this with the uploaded image file
Upvotes: 1
Views: 4142
Reputation: 11
I don't know how you prefer to do things me in my case I used axios and the FormData class
my reactjs code
import React,{ ChangeEvent, useState } from "react";
import axios from "axios";
const UploadFile = () => {
const [file, setFile] = useState<any>();
const onChange = (file: ChangeEvent) => {
const { files } = file.target as HTMLInputElement;
if (files && files.length !== 0) {
setFile(files[0]);
}
}
const handleUpload = async () => {
const formData = new FormData();
formData.append('file', file)
const upload = await axios({
url:"http://localhost:4000/upload",
method:"post",
headers:{
Authorization: `Bearer your token`
},
data:formData
}).then(r => r);
console.log(upload);
}
return (
<div>
<form onSubmit={e => e.preventDefault()}>
<input type="file" onChange={onChange} />
<button onClick={handleUpload}>upload</button>
</form>
</div>
)
}
export default UploadFile
and my nestjs code
import { Controller, Post, UploadedFile, UseGuards, UseInterceptors } from "@nestjs/common";
import { diskStorage } from "multer";
import { randomUUID } from 'crypto';
import Path = require('path');
import { FileInterceptor} from '@nestjs/platform-express';
import { JwtAuthGuard } from "src/auth/guard/jwt.auth.guard";
const storage = {
storage : diskStorage({
destination: 'src/uploads/files',
filename: (req, file, cb) =>{
const filename: string = 'myfile-' + randomUUID();
const extension: string = Path.parse(file.originalname).ext;
cb(null, `${filename}${extension}`)
}
})
}
@Controller('upload')
export class UploadController {
// @UseGuards(JwtAuthGuard) your methode of guard
@Post()
@UseInterceptors(FileInterceptor('file', storage))
uploaiFile(
@UploadedFile() file:any
){
console.log(file)
return file
}
}
Upvotes: 1