Golang file upload to s3 using OS Open

匿名 (未验证) 提交于 2019-12-03 10:24:21

问题:

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 ..

回答1:

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)) ... 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!