An Interest In:
Web News this Week
- March 28, 2024
- March 27, 2024
- March 26, 2024
- March 25, 2024
- March 24, 2024
- March 23, 2024
- March 22, 2024
Image upload using Golang and React
Golang is a blockbuster server side language in the field of efficiency and concurrency. If you are a Nodejs developer definitely you will come across express js for building your web api services. Gofiber is exactly like the express framework for golang and no doubt it booms with the efficiency of Fasthttp and golang.
In this blog post we will create a simple image upload server using gofiber and we will use reactjs for frontend to select image from file and upload to server.
we will use axios for http request to server and it is really awesome when we deal with implementing authentication and handling lots of api requests. It has lots of features which make life easy when dealing with api in react.
we will use chakra ui for designing material like button , images and layout it shins in Accessibility that directly effect better SEO.
library and tools we will use
- golang
- gofiber
- reactjs
- axios
- chakra ui
Setup backend
create new directory and enter into it
mkdir go-react-image-uploadcd go-react-image-upload
create a new directory server
inside go-react-image-upload
and enter into it
mkdir server cd server
Setup go environment
go mod init github.com/harshmangalam
install packages required for backend
go get github.com/gofiber/fiber/v2go get github.com/google/uuid
uuid will help to generate unique id so that we can name our image easily and no two image will have same name.
create new go file main.go
inside server
and start writting code
package mainimport ( "fmt" "log" "os" "strings" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/google/uuid")func main() { // create new fiber instance and use across whole app app := fiber.New() // middleware to allow all clients to communicate using http and allow cors app.Use(cors.New()) // serve images from images directory prefixed with /images // i.e http://localhost:4000/images/someimage.webp app.Static("/images", "./images") // handle image uploading using post request app.Post("/", handleFileupload) // delete uploaded image by providing unique image name app.Delete("/:imageName", handleDeleteImage) // start dev server on port 4000 log.Fatal(app.Listen(":4000"))}func handleFileupload(c *fiber.Ctx) error { // parse incomming image file file, err := c.FormFile("image") if err != nil { log.Println("image upload error --> ", err) return c.JSON(fiber.Map{"status": 500, "message": "Server error", "data": nil}) } // generate new uuid for image name uniqueId := uuid.New() // remove "- from imageName" filename := strings.Replace(uniqueId.String(), "-", "", -1) // extract image extension from original file filename fileExt := strings.Split(file.Filename, ".")[1] // generate image from filename and extension image := fmt.Sprintf("%s.%s", filename, fileExt) // save image to ./images dir err = c.SaveFile(file, fmt.Sprintf("./images/%s", image)) if err != nil { log.Println("image save error --> ", err) return c.JSON(fiber.Map{"status": 500, "message": "Server error", "data": nil}) } // generate image url to serve to client using CDN imageUrl := fmt.Sprintf("http://localhost:4000/images/%s", image) // create meta data and send to client data := map[string]interface{}{ "imageName": image, "imageUrl": imageUrl, "header": file.Header, "size": file.Size, } return c.JSON(fiber.Map{"status": 201, "message": "Image uploaded successfully", "data": data})}func handleDeleteImage(c *fiber.Ctx) error { // extract image name from params imageName := c.Params("imageName") // delete image from ./images err := os.Remove(fmt.Sprintf("./images/%s", imageName)) if err != nil { log.Println(err) return c.JSON(fiber.Map{"status": 500, "message": "Server Error", "data": nil}) } return c.JSON(fiber.Map{"status": 201, "message": "Image deleted successfully", "data": nil})}
run main.go
from server
go run main.go
Now our server is up and running we can test it using Postman
setup frontend
come outside from server
directory and generate reactjs
project using create-react-app
npx create-react-app reactjscd reactjs
install dependencies
npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 axios
index.js
import React from 'react';import ReactDOM from 'react-dom';import App from './App';ReactDOM.render( <App /> , document.getElementById('root'));
setup App.js
import { Box, ChakraProvider, Container } from "@chakra-ui/react";import Axios from "axios";import Upload from "./components/Upload";Axios.defaults.baseURL = "http://localhost:4000";function App() { return ( <ChakraProvider> <Box minH="100vh" w="100%" bg="gray.200" display="flex" alignItems="center" justifyContent="center" > <Container maxWidth="container.xl"> <Upload /> </Container> </Box> </ChakraProvider> );}export default App;
create new hook useUpload
hook in hooks
folder
hooks/useUpload.js
import { useState } from "react";import axios from "axios";import { useToast } from "@chakra-ui/react";const useUpload = () => { const [image, setImage] = useState(null); const [loading, setLoading] = useState(false); const [uploadedImage, setUploadedImage] = useState(null); const toast = useToast(); const handleChangeImage = (e) => { setImage(e.target.files[0]); }; const handleUploadImage = async () => { try { setLoading(true); const formData = new FormData(); formData.append("image", image); const res = await axios.post("/", formData); if (res.data.data) { console.log(res.data); setUploadedImage(res.data.data); toast({ title: "Image Uploaded", description: res.data.message, status: "success", duration: 4000, isClosable: true, }); } } catch (error) { console.log(error); } finally { setImage(null); setLoading(false); } }; const handleRemoveImage = async () => { try { setLoading(true); const res = await axios.delete(`/${uploadedImage.imageName}`); if (res.data) { console.log(res.data); setUploadedImage(null); toast({ title: "Image Deleted", description: res.data.message, status: "success", duration: 4000, isClosable: true, }); } } catch (error) { console.log(error); } finally { setLoading(false); } }; return { image, uploadedImage, loading, handleChangeImage, handleUploadImage, handleRemoveImage, };};export default useUpload;
create Upload.js
inside components
folder
components/Upload.js
import { Button, Heading, VStack, Image, HStack, Tag } from "@chakra-ui/react";import React from "react";import { useRef } from "react";import useUpload from "../hooks/useUpload";function Upload() { const imageRef = useRef(null); const { loading, image, handleRemoveImage, handleChangeImage, handleUploadImage, uploadedImage, } = useUpload(); return ( <> <input style={{ display: "none" }} type="file" accept="image/*" ref={imageRef} onChange={handleChangeImage} /> <VStack> <Heading>Image uploading using Golang and Reactjs</Heading> <Button onClick={() => imageRef.current.click()} colorScheme="blue" size="lg" > Select Image </Button> </VStack> {image && ( <VStack my="4"> <Image src={URL.createObjectURL(image)} width="300px" height="300px" alt="selected image..." /> <Button onClick={handleUploadImage} variant="outline" colorScheme="green" isLoading={loading} > Upload </Button> </VStack> )} {uploadedImage && ( <VStack my="4"> <Image src={uploadedImage.imageUrl} width="300px" height="300px" alt={uploadedImage.imageName} /> <HStack> <Tag variant="outline" colorScheme="blackAlpha"> ~ {Math.floor(uploadedImage.size / 1024)} Kb </Tag> <Button variant="solid" colorScheme="red" onClick={handleRemoveImage} isLoading={loading} > Delete </Button> </HStack> </VStack> )} </> );}export default Upload;
Original Link: https://dev.to/harshmangalam/image-upload-using-golang-and-react-29n1
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To