使用操作系统打开Golang文件上传到s3 [英] Golang file upload to s3 using OS Open
问题描述
我试图使用Golang和amazon s3 api将图像上传到我的s3帐户。我可以得到想象上传,如果我硬编码直接路径,如
file,err:= os.Open(/用户/ JohnSmith / Documents / pictures / cars.jpg)
推迟file.Close()
if err!= nil {
fmt.Printf(err opening file:%s,如果我像这样硬编码的文件路径那么图片将是上传到我的s3帐户。但是这种方法并不好,因为我不能直接将图像路径硬编码到我想要上传的所有图像上。我的问题是我怎样才能上传图像,而不必硬编码的路径。这将是一个用户将上传图像的API的一部分,所以我显然不能有一个硬编码的路径。这是我的代码第一个HTML < form method =postenctype =multipart / form-dataaction = profile_image >
< h2>图片上传< / h2>
< p>< input type =filename =fileid =file/> < / p为H.
< p> < input type =submitvalue =Upload Image>< / p>
< / form>
然后这是我的HTTP Post函数方法
< pre $ func UploadProfile(w http.ResponseWriter,r * http.Request){
r.ParseForm()
var resultt string
resultt =Hi
sess,_:= session.NewSession(& aws.Config {
Region:aws.String(us-west-2),
证书:credentials.NewStaticCredentials(aws_access_key_id,aws_secret_access_key,),
$ b})
svc:= s3.New(sess)
文件,err:= os.Open(Users / JohnSmith / Documents / pictures / cars.jpg)
推迟file.Close()
if err!= nil {
fmt.Printf (err打开文件:%s,err)
}
fileInfo,_:= file.Stat()
size:= fileInfo.Size()
buffer:= make([] byte,size)//读取文件内容到缓冲区
file.Read(buffer)
fileBytes:= bytes。 NewReader(buffer)
fileType:= http.DetectContentType(buffer)
path:= file.Name()
params: =& s3.PutObjectInput {
桶:aws.String(my-bucket),
键:aws.String(path),
正文:fileBytes,
ContentLength :aws.Int64(size),
ContentType:aws.String(fileType),
}
resp,err:= svc.PutObject(params)
if err!= nil {
fmt.Printf(bad response:%s,err)
}
fmt.Printf(response%s,awsutil.StringValue(resp))
$ b $ p
$ b 这是我完整的代码,但是当我尝试做一些诸如 (b)>
file,err:= os.Open(file)
推迟file.Close()
if err!= nil {
fmt.Printf(err打开文件:%s,err)
}
我得到以下错误:
http:panic serving [:: 1]:55454:runtime错误:无效的内存地址或零指针解引用
goroutine 7 [running]:
err打开文件:打开文件:没有这样的文件或目录net / http。(* conn).serve.func1(0xc420076e80)
我无法使用绝对路径(filepath.Abs())文件将在GoPath之外,正如其他用户将会上传。有没有反正我可以得到一个相对路径..
解决方案 POST到您的API后,图像被临时保存在一个操作系统临时目录(不同的操作系统的)是默认的。例如:
func GetTempLoc(文件名字符串)string {
返回字符串。 TrimRight(os.TempDir(),/)+/+ filename
}
其中:
- filename是一个header.Filename,即您的POST请求中收到的文件名。在Gin-Gonic框架中,您可以在请求处理程序中获取它:
if err!= nil {
return,err
}
推迟文件。关闭()
示例: https://github.com/gin-gonic/gin#another-example-upload-file 。
我相信在你的框架中会有一个模拟的。
- os.TempDir()一个功能去给你一个临时文件夹(详细信息: https://golang.org/pkg/os/
- TrimRight用于确保os.TempDir的结果在不同的操作系统上是一致的
然后用它作为
文件,err:= os.Open(GetTempLoc(fileName) )
...
I am trying to upload an Image to my s3 account using Golang and the amazon s3 api . I can get the imagine uploaded if I hard code the direct path such as
file, err := os.Open("/Users/JohnSmith/Documents/pictures/cars.jpg")
defer file.Close()
if err != nil {
fmt.Printf("err opening file: %s", err)
}
if I hard code the file path like that then the picture will be uploaded to my s3 account . However that approach is not good as I can't obviously hard code the direct image path to every image that I want to upload . My question is how can I upload images without having to Hardcode the path . This will be apart of an API where users will upload images so I clearly can not have a hard coded path . This is my code first the HTML
<form method="post" enctype="multipart/form-data" action="profile_image">
<h2>Image Upload</h2>
<p><input type="file" name="file" id="file"/> </p>
<p> <input type="submit" value="Upload Image"></p>
</form>
then this is my HTTP Post function method
func UploadProfile(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
var resultt string
resultt = "Hi"
sess, _ := session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
Credentials: credentials.NewStaticCredentials(aws_access_key_id,aws_secret_access_key, ""),
})
svc := s3.New(sess)
file, err := os.Open("Users/JohnSmith/Documents/pictures/cars.jpg")
defer file.Close()
if err != nil {
fmt.Printf("err opening file: %s", err)
}
fileInfo, _ := file.Stat()
size := fileInfo.Size()
buffer := make([]byte, size) // read file content to buffer
file.Read(buffer)
fileBytes := bytes.NewReader(buffer)
fileType := http.DetectContentType(buffer)
path := file.Name()
params := &s3.PutObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String(path),
Body: fileBytes,
ContentLength: aws.Int64(size),
ContentType: aws.String(fileType),
}
resp, err := svc.PutObject(params)
if err != nil {
fmt.Printf("bad response: %s", err)
}
fmt.Printf("response %s", awsutil.StringValue(resp))
}
That is my full code above however when I try to do something such as
file, err := os.Open("file")
defer file.Close()
if err != nil {
fmt.Printf("err opening file: %s", err)
}
I get the following error
http: panic serving [::1]:55454: runtime error: invalid memory address or nil pointer dereference
goroutine 7 [running]:
err opening file: open file: no such file or directorynet/http.(*conn).serve.func1(0xc420076e80)
I can't use absolute path (filepath.Abs()) because some of the files will be outside of the GoPath and as stated other users will be uploading. Is there anyway that I can get a relative path ..
After POST to your API, images are temporarily saved in a OS's temp directory (different for different OS's) by default. To get this directory you can use, for example:
func GetTempLoc(filename string) string {
return strings.TrimRight(os.TempDir(), "/") + "/" + filename
}
Where:
- filename is a header.Filename, i.e. file name received in your POST request. In Gin-Gonic framework you get it in your request handler as:
file, header, err := c.Request.FormFile("file")
if err != nil {
return out, err
}
defer file.Close()
Example: https://github.com/gin-gonic/gin#another-example-upload-file.
I'm sure in your framework there will be an analogue.
- os.TempDir() is a function go give you a temp folder (details: https://golang.org/pkg/os/#TempDir).
- TrimRight is used to ensure result of os.TempDir is consistent on different OSs
And then you use it as
file, err := os.Open(GetTempLoc(fileName))
...
这篇关于使用操作系统打开Golang文件上传到s3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!