Asdf1234567
Asdf1234567

Reputation: 560

How to upload image file using ReactJS to api using NestJS with bytea datatype

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

enter image description here

This is the table from PostgreSQL for that entity

enter image description here

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

Answers (1)

adonai mbula
adonai mbula

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

Related Questions