1

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

1 Answer 1

1

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
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.