-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
210 lines (195 loc) · 5.96 KB
/
main.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"flag"
"fmt"
"github.com/joho/godotenv"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/scottleedavis/go-exif-remove"
)
func getURL(dns string, bucket string, filename string, includeBucketName bool) string {
retVal := ""
if includeBucketName {
retVal = "https://" + dns + "/" + bucket + "/" + filename
} else {
retVal = "https://" + dns + "/" + filename
}
return retVal
}
func checkIfFileIsValid(file *os.File) bool {
fileStat, err := file.Stat()
if err != nil {
return false
} else if fileStat.Size() == 0 {
return false
} else {
return true
}
}
func hashFile(file os.File) string {
f, _ := os.Open(file.Name())
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
return hex.EncodeToString(h.Sum(nil))
}
func getContentTypeOfFileFromFileName(file *os.File) string {
contentType := "application/octet-stream"
fileName := file.Name()
if strings.HasSuffix(fileName, ".jpg") || strings.HasSuffix(fileName, ".jpeg") {
contentType = "image/jpeg"
} else if strings.HasSuffix(fileName, ".png") {
contentType = "image/png"
} else if strings.HasSuffix(fileName, ".gif") {
contentType = "image/gif"
} else if strings.HasSuffix(fileName, ".tif") || strings.HasSuffix(fileName, ".tiff") {
contentType = "image/tiff"
} else if strings.HasSuffix(fileName, ".txt") {
contentType = "text/plain"
} else if strings.HasSuffix(fileName, ".webp") {
contentType = "image/webp"
} else if strings.HasSuffix(fileName, ".svg") {
contentType = "image/svg+xml"
} else if strings.HasSuffix(fileName, ".ico") {
contentType = "image/vnd.microsoft.icon"
}
return contentType
}
func main() {
err := godotenv.Load(os.Getenv("HOME") + "/.config/minio-image-uploader.env")
if err != nil {
log.Fatal(err)
return
}
// read command line flags
sourcePathFlag := flag.String("src", "", "the source file you want to upload")
destPrefixFlag := flag.String("prefix", "", "the destination prefix")
endpoint := flag.String("endpoint", os.Getenv("S3_ENDPOINT"), "the S3 endpoint")
accessKey := flag.String("access-key", os.Getenv("S3_ACCESSKEY"), "the access key")
bucketName := flag.String("bucket", os.Getenv("S3_BUCKETNAME"), "the name of the S3 Bucket")
secretKey := flag.String("secret-key", os.Getenv("S3_SECRETKEY"), "secret key")
accessDns := flag.String("access-dns", *endpoint, "the dns")
accessUrlNoBucketName := flag.Bool("no-access-url-bucket-name", false, "The bucket name should not appear in the printed access url")
printURL := flag.Bool("print-url", false, "print the url to access this object")
getShareURL := flag.Bool("share-url", false, "get the share url")
debugOutput := flag.Bool("verbose", false, "if you want to get verbose output")
flag.Parse()
if len(*sourcePathFlag) == 0 {
println("please provide the path to the source file using the \"-src\" flag")
return
}
imagePath := *sourcePathFlag
if len(*destPrefixFlag) == 0 {
println("please provide a prefix to be prepended when uploading using the \"-prefix\" flag")
return
}
if len(*endpoint) == 0 {
println("Endpoint is not definied. it was neither defined as environment variable nor as cmdline (\"-endpoint s3.example.org\") flag")
return
}
if len(*accessKey) == 0 {
println("Access key is not definied. it was neither defined as environment variable nor as cmdline flag")
return
}
if len(*bucketName) == 0 {
println("Bucket name is not definied. it was neither defined as environment variable nor as cmdline flag (\"-bucket my-bucket\")")
return
}
prefix := *destPrefixFlag
// Open the image file.
if *debugOutput {
// debug output
log.Println("opening file: " + imagePath)
}
file, err := os.Open(imagePath)
filename := filepath.Base(imagePath)
if err != nil {
log.Fatal(err)
}
if *debugOutput {
fileStat, err := file.Stat()
if err != nil {
log.Panic(err)
}
log.Printf("opened file has the size of %d\n", fileStat.Size())
}
defer file.Close()
// Save the image to a temporary file.
tempFile, err := ioutil.TempFile("", "")
if err != nil {
log.Fatal(err)
}
bytes, err := ioutil.ReadFile(file.Name())
if *debugOutput {
log.Println("trying to clean exif data from file")
}
cleanBytes, err := exifremove.Remove(bytes)
_, err = tempFile.Write(cleanBytes)
if err != nil {
log.Panic(err)
}
if !checkIfFileIsValid(tempFile) {
log.Println("cleaned file is invalid. Falling back to uncleaned file")
_, err = tempFile.Write(bytes)
if err != nil {
log.Panic(err)
}
}
// Upload the image to Minio.
useSSL := true
if os.Getenv("S3_USESSL") == "false" {
useSSL = false
}
objectName := prefix + "/" + hashFile(*file) + "/" + filename
// Initialize the Minio client.
minioClient, err := minio.New(*endpoint, &minio.Options{
Creds: credentials.NewStaticV4(*accessKey, *secretKey, ""),
Secure: useSSL,
})
if err != nil {
log.Fatal(err)
}
// Set the content type of the object based on its file extension.
contentType := getContentTypeOfFileFromFileName(tempFile)
UserTags := make(map[string]string)
UserTags["agent"] = "Ryes-Minio-Image-Uploader"
if *getShareURL {
UserTags["generatedWithShareURL"] = "true"
}
// Upload the object to Minio.
_, err = minioClient.FPutObject(context.Background(), *bucketName, objectName, tempFile.Name(), minio.PutObjectOptions{
ContentType: contentType,
UserTags: UserTags,
})
if err != nil {
log.Fatal(err)
}
if *printURL {
fmt.Println(getURL(*accessDns, *bucketName, objectName, !*accessUrlNoBucketName))
} else if *getShareURL {
shareURL, _ := minioClient.PresignedGetObject(context.Background(), *bucketName, objectName, time.Duration(24*time.Hour), nil)
fmt.Println(shareURL)
} else {
fmt.Printf("Uploaded %s to %s/%s\n", imagePath, *bucketName, objectName)
}
err = tempFile.Close()
if err != nil {
log.Panic(err)
}
defer os.Remove(tempFile.Name())
err = file.Close()
if err != nil {
log.Panic(err)
}
}