0% found this document useful (0 votes)
60 views

How To Upload Single and Multiple Files in Golang 2024

Uploaded by

walteravelin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
60 views

How To Upload Single and Multiple Files in Golang 2024

Uploaded by

walteravelin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Home Categories     

How To Upload Single and Multiple Files


in Golang
May 4, 2023 0 Comments 37

This article will teach you how to upload single and multiple files on a

Golang web server. The tutorial focuses on image upload, but the concepts
can be extended and used for any file type.

···

 Now Playing

Node.Js + Prisma + Post…


Node.Js + Prisma + Postgresql Access & Refresh Toke…

When building APIs for either Web, Mobile, or Desktop apps, very often, the
need to make provision for file upload arises. Therefore, knowing how to
upload and process files in Golang will give you more confidence when

searching for jobs.

At the end of this comprehensive guide, you should know how to:

Upload a single image and store it on the disk

Upload multiple images and store them on the disk

Upload and resize a single image before storing it on the disk

Upload and resize multiple images before storing them on the disk

More practice:

How to Implement Two-factor Authentication (2FA) in React.js

How to Implement Two-factor Authentication (2FA) in Node.js

Two-factor Authentication (2FA) in FastAPI and Python

How to Implement (2FA) Two-factor Authentication in Golang


Table of Contents

Prerequisites

While this tutorial is designed to be beginner friendly, these are the

prerequisites the reader is expected to possess:

···
Have the latest version of Golang installed on your system

Have basic knowledge of Golang


Have a basic understanding of API architectures

Basic knowledge of Gin Gonic will be beneficial

Run the Golang File Upload Project Locally


1. If you don’t have Golang installed, visit https://go.dev/doc/install to
download and install the binary executable on your machine.

2. Download or clone the Upload Single and Multiple Files in Golang

source code from https://github.com/wpcodevo/file_upload_golang

3. Open the integrated terminal in your IDE and run go mod tidy to

install all the necessary packages.

4. Start the Gin Gonic HTTP server with go run main.go or use the
https://github.com/cosmtrek/air library if you need the hot-reloading

feature.

5. Open an API testing software or visit http://localhost:8000 to


upload the files.

Step 1 – Setup the Golang Project

To get started, navigate to the location you would like to set up the project

and create a folder named file_upload_golang . Once the directory has

been created, open it with an IDE or text editor like VS Code.

1 mkdir file_upload_golang && cd file_upload_golang && code .

Next, initialize the Golang project by running:

1 go mod init github.com/:github_username/name_of_project

Now that you’ve created the project module, install the Gin Gonic package
with this command. Gin Gonic is an HTTP web framework written in Go.
1 go get -u github.com/gin-gonic/gin

Next, create a main.go file and add the following code snippets:

main.go

1 package main
2
3 import (
4 "github.com/gin-gonic/gin"
5 )
6
7 func main() {
8 router := gin.Default()
9
10 router.GET("/healthchecker", func(ctx *gin.Context) {
11 ctx.JSON(200, gin.H{"status": "success", "message": "How to Upload Sing
12 })
13
14 router.Run(":8000")
15 }
16

The above code will create a Gin Gonic engine instance, add a health
checker route to the middleware pipeline and start the HTTP server on port

8000. Start the Gin server by running go run main.go .

Open a new tab in your browser and visit

http://localhost:8000/healthchecker to see the JSON object sent by

the Golang API.

Congrats if you have made it this far. We will continue by creating the file

upload components with HTML, CSS, and JavaScript. After that, we will use
Gin Gonic to parse and render the HTML markup.
Step 2 – Create the File Upload Components

Below is a preview of the file upload components. The HTML markup will

have three components:

OFERTAS DO CONSUMIDOR

OS DESCONTOS
CHEGARAM

Ver Ofertas
Beyond Fast

Image preview area

Single file upload component

Multiple file upload component


X
FileuploadinGolang X +
ocalhost:8000

HowtoSetup tRPCCRUD TS
Golang
Forget/Reset
SQLC Reset
Golang
Password
API NEXT.
Password

JWT GOFileUpload
Authentication
CRUD TS

Authorization mongoDB GraphQLAPI ЛЕХТ.

SingleFileUpload

ChooseFileNofilechosen

MultipleFileUpload

ChooseFiles7files

To spin up the file upload components, create a templates/index.html

file and add the following HTML markup.

templates/index.html

90 imgHolder.appendChild(imgElement);
91 IMAGE_PREVIEW.appendChild(imgHolder);
92 } catch (error) {
93 alert(error.message);
94 }
95 });
96
97 // Mulitple File Upload
98 document
99 .getElementById("mulitple_files_upload")
100 .addEventListener("change", async (event) => {
101 try {
102 let formData = new FormData();
103 for (let key in event.target.files) {
104 formData.append("images", event.target.files[key]);
105 }
106 const data = await fetch(`${SERVER_ENDPOINT}/upload/multiple
107 body: formData,
108 method: "POST",
109 }).then((res) => res.json());
110
111 data.filepaths.forEach((filepath) => {
112 const imgHolder = document.createElement("div");
113 const imgElement = document.createElement("img");
114 imgHolder.classList.add("file-preview__el");
115 imgElement.classList.add("file-preview__img");
116 imgElement.src = filepath;
117 imgHolder.appendChild(imgElement);
118 IMAGE_PREVIEW.appendChild(imgHolder);
119 });
120 } catch (error) {
121 alert(error.message);
122
123 }
124 });
125 </script>
126 </body>
</html>

Quite a lot is happening in the above code, let’s break it down:

First, we created a basic markup that contains the file upload

components and some basic styling to improve the visual appearance


of the components.

Then, we wrote some logic to upload single and multiple files with

JavaScript.

Finally, we wrote some logic with JavaScript to dynamically display the

images after the files have been saved to the disk.

Now that we have the HTML template, let’s write some code to render

index.html on the root route. Open main.go file and replace its content

with the code below.

main.go

1 package main
2
3 import (
4 "net/http"
5
6 "github.com/gin-gonic/gin"
7 )
8
9 func main() {
10 router := gin.Default()
11
12 router.LoadHTMLGlob("templates/*")
13 router.GET("/healthchecker", func(ctx *gin.Context) {
14 ctx.JSON(200, gin.H{"status": "success", "message": "How to Upload Sing
15 })
16
17 router.GET("/", func(ctx *gin.Context) {
18 ctx.HTML(http.StatusOK, "index.html", nil)
19 })
20 router.Run(":8000")
21 }
22

After that, start the Gin HTTP server with go run main.go and open

http://localhost:8000/ in a new tab to see the rendered HTML.

Let’s go ahead and write the code required for uploading and processing
the files.

Step 3 – Upload a Single File in Golang

In this section, you will create a route function to retrieve the uploaded file

and store it in the filesystem. Handling file upload in Golang can be a little

challenging especially when you are a beginner. Luckily, Gin provides a


simple way to handle uploaded files and store them on the disk.

To handle
 a single file, we will use Gin’s .FromFile() method that’s

available on the context object to retrieve the uploaded file from the multi-

part content.

main.go


1 func uploadSingleFile(ctx *gin.Context) {
2
 file, header, err := ctx.Request.FormFile("image")
3 if err != nil {
4
 ctx.String(http.StatusBadRequest, fmt.Sprintf("file err : %s"
5 return
6 }
7
8 fileExt := filepath.Ext(header.Filename)
9 originalFileName := strings.TrimSuffix(filepath.Base(header.Filename
10 now := time.Now()
11 filename := strings.ReplaceAll(strings.ToLower(originalFileName
12 filePath := "http://localhost:8000/images/single/" + filename
13
14 out, err := os.Create("public/single/" + filename)
15 if err != nil {
16 log.Fatal(err)
17 }
18 defer out.Close()
19 _, err = io.Copy(out, file)
20 if err != nil {
21 log.Fatal(err)
22 }
23 ctx.JSON(http.StatusOK, gin.H{"filepath": filePath})
24 }

Let’s evaluate the above code. First, we attempt to retrieve the file with the

name “image” from the multi-part content and check if the file is received
successfully. To avoid conflicts with the file names, we appended a Unix

time to the original file name, called the os.Create() method to create
the file in the public/single/ directory, and used an if statement to

check if the file has been created.


Conheça DESCONTO
EXTRA
lugares
RESERVE AGORA

10 % CÓDIGO: LATAMBR10
After that, we called the io.Copy() method to copy the uploaded file to
incríveis
#StaySafewithMelia

the file system at the specified destination. If everything goes well, and the
file was stored on the disk, we will return the file path to the client.

I didn’t use Gin’s ctx.SaveUploadedFile(file, dst) method

because it had some limitations.

Step 4 – Resize a Single File in Golang

Now let’s handle the case where we want to process the uploaded file
before storing it in the file system. Since we are dealing with images, we will
use the https://github.com/disintegration/imaging package to process

the uploaded image before storing it on the disk.

To begin, open your terminal and install the Imaging package.

···
1 go get -u github.com/disintegration/imaging

The Imaging package provides a bunch of image processing functions but


we will only use the .Resize() function to reduce the complexity of the
project. Before we can resize the image, we first need to retrieve the file

from the multi-part content with the .FormFile() method, generate a


Unix time, and append it to the filename.

After that, we will call the image.Decode() method to decode the file from

multipart.File to image.Image . If everything goes on well, we will resize

the image to a specific aspect ratio by utilizing the imaging.Resize()


function.

···

Read the Imaging documentation for more details about the

various resampling filters supported by the imaging.Resize()


function.

Once the image has been resized and there is no error, we will call the

imaging.Save() method to save the image on the disk at the specified


destination.

···

main.go

1 func uploadResizeSingleFile(ctx *gin.Context) {


2 file, header, err := ctx.Request.FormFile("image")
3 if err != nil {
4 ctx.String(http.StatusBadRequest, fmt.Sprintf("file err : %s"
5 return
6 }
7
8 fileExt := filepath.Ext(header.Filename)
9 originalFileName := strings.TrimSuffix(filepath.Base(header.Filename
10 now := time.Now()
11 filename := strings.ReplaceAll(strings.ToLower(originalFileName
12 filePath := "http://localhost:8000/images/single/" + filename
13
14 imageFile, _, err := image.Decode(file)
15 if err != nil {
16 log.Fatal(err)
17 }
18 src := imaging.Resize(imageFile, 1000, 0, imaging.Lanczos)
19 err = imaging.Save(src, fmt.Sprintf("public/single/%v", filename
20 if err != nil {
21 log.Fatalf("failed to save image: %v", err)
22 }
23
24 ctx.JSON(http.StatusOK, gin.H{"filepath": filePath})
25 }
Step 5 – Upload Multiple Files in Golang

Now let’s handle the case where the client uploads multiple files to the

server. To do that, we will create a route function that will extract the files
from the multipart content, modify the origin filenames, and save the files
to the filesystem. We can manually parse and iterate over each file but Gin

provides a ctx.MultipartForm() function that can parse the multipart


form and the uploaded files.

···

main.go

1 func uploadMultipleFile(ctx *gin.Context) {


2 form, _ := ctx.MultipartForm()
3 files := form.File["images"]
4 filePaths := []string{}
5 for _, file := range files {
6 fileExt := filepath.Ext(file.Filename)
7 originalFileName := strings.TrimSuffix(filepath.Base(file.
8 now := time.Now()
9 filename := strings.ReplaceAll(strings.ToLower(originalFileName
10 filePath := "http://localhost:8000/images/multiple/" + filename
11
12 filePaths = append(filePaths, filePath)
13 out, err := os.Create("./public/multiple/" + filename)
14 if err != nil {
15 log.Fatal(err)
16 }
17 defer out.Close()
18
19 readerFile, _ := file.Open()
20 _, err = io.Copy(out, readerFile)
21 if err != nil {
22 log.Fatal(err)
23 }
24 }
25
26 ctx.JSON(http.StatusOK, gin.H{"filepath": filePaths})
27 }

We parsed the uploaded files by calling Gin’s ctx.MultipartForm()

method and stored the result in a form variable. Then, we extracted the
multipart content with the name images from form.File[] , looped

through the list of files, modified the filenames, and stored the files on the
disk.

···

If everything goes well and the files were stored in the filesystem, a slice
holding the file paths will be returned to the client.
···

···

Step 6- Resize Multiple Files in Golang

This route handler is similar to the uploadMultipleFile function but this

time we will resize the images before storing them in the filesystem. After
looping through the multipart files, Imaging‘s image.Decode() method will
be called to decode the images from multipart.File to image.Image .
···

If the images were decoded successfully, the imaging.Resize() method will


be evoked to crop each image before the imaging.Save() method will be
called to save the file to the filesystem.

main.go

···

1 func uploadResizeMultipleFile(ctx *gin.Context) {


2 form, _ := ctx.MultipartForm()
3 files := form.File["images"]
4 filePaths := []string{}
5 for _, file := range files {
6 fileExt := filepath.Ext(file.Filename)
7 originalFileName := strings.TrimSuffix(filepath.Base(file.
8 now := time.Now()
9 filename := strings.ReplaceAll(strings.ToLower(originalFileName
10 filePath := "http://localhost:8000/images/multiple/" + filename
11
12 filePaths = append(filePaths, filePath)
13 readerFile, _ := file.Open()
14 imageFile, _, err := image.Decode(readerFile)
15 if err != nil {
16 log.Fatal(err)
17 }
18 src := imaging.Resize(imageFile, 1000, 0, imaging.Lanczos)
19 err = imaging.Save(src, fmt.Sprintf("public/multiple/%v", filename
20 if err != nil {
21 log.Fatalf("failed to save image: %v", err)
22 }
23 }
24
25 ctx.JSON(http.StatusOK, gin.H{"filepath": filePaths})
26 }

Step 7 – Register the Routes

Now let’s create routes to evoke the route handlers. The API will have four
routes:

/ – Renders the HTML template on the root route

/images – A route for accessing the files stored in the filesystem

/upload/single – Upload a single file

/upload/multiple – Uploads multiple files

Because the files are to be stored on the disk, we need to create folders that
represent the folder structure we passed to the os.Create() and

imaging.Save() methods. To do that, we will utilize an init function to

create the folders if they don’t exists before the main function gets called.

main.go
1 package main
2
3 import (
4 "errors"
5 "fmt"
6 "image"
7 "io"
8 "log"
9 "net/http"
10 "os"
11 "path/filepath"
12 "strings"
13 "time"
14
15 "github.com/gin-gonic/gin"
16
17 "github.com/disintegration/imaging"
18 )
19
20 func uploadResizeSingleFile(ctx *gin.Context) {
21 file, header, err := ctx.Request.FormFile("image")
22 if err != nil {
23 ctx.String(http.StatusBadRequest, fmt.Sprintf("file err : %s"
24 return
25 }
26
27 fileExt := filepath.Ext(header.Filename)
28 originalFileName := strings.TrimSuffix(filepath.Base(header.Filename
29 now := time.Now()
30 filename := strings.ReplaceAll(strings.ToLower(originalFileName
31 filePath := "http://localhost:8000/images/single/" + filename
32
33 imageFile, _, err := image.Decode(file)
34 if err != nil {
35 log.Fatal(err)
36 }
37 src := imaging.Resize(imageFile, 1000, 0, imaging.Lanczos)

After implementing all the above code, start the Gin HTTP server by running

go run main.go .
···

Conclusion

Congrats! You have made it to the end, and I hope you’ve learned how to
upload and process files in Golang. Take it up as a challenge, add more

file-processing features, and perhaps do something even more awesome


with the knowledge obtained from this tutorial.

You can find the complete code on GitHub.

 Download Source Code

Share Article:       

https://codevoweb.com/how-to-upload-single-and-multiple-files-in-golang/
Tags: Golang Golang API

May 28, 2023

Two-factor Authentication (2FA) in FastAPI and Python

May 4, 2023

How To Setup and Use Prisma in Deno

Leave a Reply

Comment

Name Email

Save my name, email, and website in this browser for the next time I comment.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of
Service apply.

Post Comment
This site uses Akismet to reduce spam. Learn how your comment data is processed.

Support Me!

···

Recent posts
February 10, 2024

Setting up Drizzle ORM with NextAuth.js in Next.js 14

February 7, 2024

Set up Google and GitHub OAuth with NextAuth in Next.js 14

February 7, 2024

Implement Authentication with NextAuth in Next.js 14

February 5, 2024

Setup and Use NextAuth.js in Next.js 14 App Directory

Categories

C# (2)

C++ (1)

CSS / SCSS (3)

Deno (8)

Golang (28)

JavaScript (4)

NextJs (36)

NodeJS (32)

Programming (19)

Python (17)

React (35)

Rust (31)
Svelte (5)

Vue (7)
···
Tag Cloud

.NET C# create website Deno developers Django DOM

DOM methods fastapi Golang Golang API graphql gRPC API

html template JavaScript JavaScript DOM landing page

Material-UI Material UI MUI NextJs nodejs nodejs api

Prisma programmers programming language programming terms

pure nodejs api python python development React

React Hook Form ReactJs React Query RTK Query Rust Svelte

SvelteKit TypeScript vscode vscode extension

vscode tips and tricks VueJs website Yew.rs

Copyright @ 2024 CodevoWeb


Privacy Policy | Terms & Conditions | About Us | Sitemap | Contact Us

WordPress Theme by EstudioPatagon

···

You might also like