-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathupload.go
135 lines (109 loc) · 4.59 KB
/
upload.go
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package handlers
import (
"fmt"
"io"
"net/http"
"path/filepath"
firebase "firebase.google.com/go"
"github.com/gofiber/fiber/v2"
uuid "github.com/gofrs/uuid"
appConfig "github.com/red-gold/telar-web/micros/storage/config"
"google.golang.org/api/option"
coreSetting "github.com/red-gold/telar-core/config"
"github.com/red-gold/telar-core/pkg/log"
"github.com/red-gold/telar-core/types"
"github.com/red-gold/telar-core/utils"
)
// @Summary Upload a file to the storage
// @Description Upload a file to the storage and return the download URL
// @Tags upload
// @Accept multipart/form-data
// @Produce json
// @Security JWT
// @Param Authorization header string true "Authentication" default(Bearer <Add_token_here>)
// @Param uid path string true "User ID"
// @Param dir path string true "Directory name"
// @Param file formData file true "File to upload"
// @Success 200 {object} object{payload=string}
// @Failure 400 {object} utils.TelarError
// @Failure 401 {object} utils.TelarError
// @Failure 500 {object} utils.TelarError
// @Router /{uid}/{dir} [post]
func UploadeHandle(c *fiber.Ctx) error {
ctx := c.Context()
currentUser, ok := c.Locals("user").(types.UserContext)
if !ok {
log.Error("[UploadeHandle] Can not get current user")
return c.Status(http.StatusUnauthorized).JSON(utils.Error("invalidCurrentUser",
"Can not get current user"))
}
storageConfig := &appConfig.StorageConfig
log.Info("Hit upload endpoint by userId : %v", currentUser.UserID)
// params from /storage/:uid/:dir
dirName := c.Params("dir")
if dirName == "" {
errorMessage := fmt.Sprintf("Directory name is required!")
log.Error(errorMessage)
return c.Status(http.StatusBadRequest).JSON(utils.Error("directoryNameRequired", "Directory name is required!"))
}
log.Info("Directory name: %s", dirName)
// FormFile returns the first file for the given key `file`
// it also returns the FileHeader so we can get the Filename,
// the Header and the size of the file
file, err := c.FormFile("file")
if err != nil {
log.Error("Error Retrieving the File %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Error Retrieving the File!"))
}
log.Info("Uploaded File: %+v", file.Filename)
log.Info("File Size: %+v", file.Size)
log.Info("MIME Header: %+v", file.Header)
extension := filepath.Ext(file.Filename)
fileNameUUID := uuid.Must(uuid.NewV4())
fileName := fileNameUUID.String()
fileNameWithExtension := fmt.Sprintf("%s%s", fileName, extension)
objectName := fmt.Sprintf("%s/%s/%s", currentUser.UserID.String(), dirName, fileNameWithExtension)
config := &firebase.Config{
StorageBucket: storageConfig.BucketName,
}
opt := option.WithCredentialsJSON([]byte(storageConfig.StorageSecret))
app, err := firebase.NewApp(ctx, config, opt)
if err != nil {
log.Error("Credential parse %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Credential parse error!"))
}
client, err := app.Storage(ctx)
if err != nil {
log.Error("Get storage client %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Get storage client!"))
}
bucket, err := client.DefaultBucket()
if err != nil {
log.Error("Get default bucket %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Get default bucket!"))
}
wc := bucket.Object(objectName).NewWriter(ctx)
multiFile, openFileErr := file.Open()
if openFileErr != nil {
log.Error("Open file error %s", openFileErr.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Open file error!"))
}
if _, err = io.Copy(wc, multiFile); err != nil {
log.Error("Copy file to storage error %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Copy file to storage error!"))
}
if err := wc.Close(); err != nil {
log.Error("Close storage writer error %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Close storage writer error!"))
}
if err := multiFile.Close(); err != nil {
log.Error("Close file writer error %s", err.Error())
return c.Status(http.StatusInternalServerError).JSON(utils.Error("internal/upload", "Close file writer error!"))
}
prettyURL := utils.GetPrettyURLf(storageConfig.BaseRoute)
downloadURL := fmt.Sprintf("%s/%s/%s/%s", *coreSetting.AppConfig.Gateway+prettyURL,
currentUser.UserID, dirName, fileNameWithExtension)
return c.JSON(fiber.Map{
"payload": downloadURL,
})
}