0

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 Answer 1

2

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))
...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.