When making a restful api uploading files is one of the key part.With go file upload is very easy to setup.This files may be images pdf or just some form data.In this post i am going to show you how easy it is to upload a file using go.
We are going to write a small program that we will use to change a user profile image.
Project Structure
Lets start with how our project structure will look like.
Note:i only show the important files.files that we use to save user on the database are not shown.
1
2
3
4
5
|
handlers
handlers.go
helpers
helpers.go
main.go
|
Writing The Code to handle file upload
We are going to write the code to retrieve and save our file from the request object.
The function takes the request object as a parameter and return an filename and error(if any occurs).
As you know we are going to be sending our files as form data(multipart/form-data) thus we need a way to retrieve the file from our request object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package helpers
import (
"net/http"
"os"
"io"
)
func FileUpload(r *http.Request) (string, error) {
//this function returns the filename(to save in database) of the saved file or an error if it occurs
r.ParseMultipartForm(32 << 20)
//ParseMultipartForm parses a request body as multipart/form-data
file, handler, err := r.FormFile("file")//retrieve the file from form data
//replace file with the key your sent your image with
if err != nil {
return "",err
}
defer file.Close() //close the file when we finish
//this is path which we want to store the file
f, err := os.OpenFile("path/to/save/image/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return "",err
}
defer f.Close()
io.Copy(f, file)
//here we save our file to our path
return handler.Filename, nil
}
|
As you can see this function has two return types
- file_name-this is what you store to the database to use in retrieving the file later.
- error-when calling this function you check error and it nil
Now that we have our function to save our file and image upload ready, its time to start using it.We are going to use the httprouter to handler our requests.
You can use a router of your choice like gorilla/mux but i personally like httprouter due to its simplicity.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package handlers
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
"kenyaappexperts/database"
"kenyaappexperts/models"
"encoding/json"
"kenyaappexperts/helpers"
)
func ChangeProfileImage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
//a function to change a profile image
userId := ps.ByName("user_id")
//getting user_id from our request object
var user models.User
userData := database.DBCon.Where("id = ?", userId).First(&user)
//reading the user whose image we want to change from the database
if userData.RecordNotFound() {
http.Error(w, "User Not Found", http.StatusNotFound)
return
}
imageName, err := helpers.FileUpload(r)
//here we call the function we made to get the image and save it
if err != nil {
http.Error(w, "Invalid Data", http.StatusBadRequest)
return
//checking whether any error occurred retrieving image
}
user.Image = imageName
//if no error we we change the profile image for our user
database.DBCon.Save(&user)
w.Header().Set("Content-Type", "application/json")
//we then return the new user details to update our user interface
json.NewEncoder(w).Encode(user)
}
|
Now we have successfully created a function to accept request to change a user profile.The last step is to expose this function and we will do this in the main.go file.
Connecting Our handler function with a router
In this final step we are going to to make a route that any time we want to change a user profiling we will be calling.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package main
import(
"github.com/julienschmidt/httprouter"
"net/http"
"kenyaappexperts/handlers"
)
func main(){
router := httprouter.New()
router.PUT("/change_profile/:user_id",handlers.ChangeProfileImage)
err := http.ListenAndServe("0.0.0.0:3000", router)
if err != nil {
log.Fatal(err)
}
}
|
In this tutorial you should have noticed we have just retrieved the file without the form data.In my next tutorial i am going to show you how to do this.
That all you need to upload a file in golang. Happy coding .You can enroll for our free courses at Codesahara.
You can also read some of our previous post.Here