I want to make functionality to post image to S3 in following steps.
- user upload image(s) on the screen.
- image files are sent to server after submitting
- images are uploaded to S3 in server side(golang).
Now issue is at 3."images are uploaded to S3 in server side(golang)."
There is nil error at server side code.
debug shows nil value at this method.
form, _ := c.MultipartForm()
Here is the codes.
//import
interface ArticleState {
title: string;
content: string;
redirect: boolean;
files: File[];
}
class Post extends React.Component<{}, ArticleState> {
constructor(props: {}) {
super(props);
this.state = {
title: '',
content: '',
redirect: false,
files: [],
};
this.handleChangeTitle = this.handleChangeTitle.bind(this);
this.handleChangeContent = this.handleChangeContent.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.renderRedirect = this.renderRedirect.bind(this);
this.handleOnDrop = this.handleOnDrop.bind(this);
}
handleOnDrop(acceptedFiles: File[]) {
this.setState({files: this.state.files.concat(acceptedFiles)});
}
handleChangeTitle(e: React.FormEvent<HTMLInputElement>) {
this.setState({title: e.currentTarget.value});
}
handleChangeContent(e: React.FormEvent<HTMLInputElement>) {
this.setState({content: e.currentTarget.value});
}
handleSubmit() {
this.setState({
redirect: true,
});
const data = {
title: this.state.title,
content: this.state.content,
files: this.state.files,
};
axios.post('http://localhost:4000/api/post', data).then(res => {
console.log(res);
});
}
renderRedirect = () => {
if (this.state.redirect) {
return <Redirect to="/post/finish" />;
}
};
render() {
return (
<Container text style={{marginTop: '3em'}}>
<Form>
<Form.Input
label="Title"
placeholder=""
name="title"
value={this.state.title}
onChange={this.handleChangeTitle}
/>
<Form.Field
label="Content"
placeholder=""
name="content"
value={this.state.content}
rows="20"
control="textarea"
onChange={this.handleChangeContent}
/>
{this.renderRedirect()}
<input type="file" id="file" hidden /> */}
<Dropzone accept="image/*" onDrop={this.handleOnDrop}>
{({getRootProps, getInputProps, open}) => (
<section>
<div {...getRootProps()} style={{margin: '20px auto'}}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
<button type="button" onClick={open}>
Open File Dialog
</button>
</div>
</section>
)}
</Dropzone>
<Form.Button content="Submit" onClick={this.handleSubmit} />
</Form>
</Container>
);
}
}
export default Post;
package main
//import
type Article struct {
ID int `json:"id"`
TITLE string `json:"title"`
CONTENT string `json:"content"`
}
var articles []Article
type Param struct {
Bucket string
Key string
Expires string
ContentType string
}
func main() {
awsAccessKeyID := "Insert Key Here"
awsSecretAccessKey := "Insert Secret Here"
token := ""
//some codes for mysql connection
router.Use(
// some codes
)
api := router.Group("/api")
{
api.POST("/post", func(c *gin.Context) {
//some codes for inserting article data in mysql
creds := credentials.NewStaticCredentials(awsAccessKeyID, awsSecretAccessKey, token)
cfg := aws.NewConfig().WithRegion("ap-northeast-1").WithCredentials(creds)
svc := s3.New(session.New(), cfg)
//Here form value is nill.
form, _ := c.MultipartForm()
files := form.File["upload[]"]
for _, file := range files {
f, err := file.Open()
defer f.Close()
fileInfo, _ := f.(*os.File).Stat()
size := fileInfo.Size()
buffer := make([]byte, size)
f.Read(buffer)
fileBytes := bytes.NewReader(buffer)
fileType := http.DetectContentType(buffer)
path := "/media/" + f.(*os.File).Name()
params := &s3.PutObjectInput{
Bucket: aws.String("bucketname"),
Key: aws.String(path),
Body: fileBytes,
ContentLength: aws.Int64(size),
ContentType: aws.String(fileType),
}
resp, err := svc.PutObject(params)
fmt.Printf("response %s", awsutil.StringValue(resp))
}
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
}
router.Run(":4000")
}
I expected image(s) are uploaded to S3, but actually not uploaded with server error.
The following is error messages.
POST http://localhost:4000/api/post 500 (Internal Server Error)
createError.js:17 Uncaught (in promise) Error: Request failed with status code 500
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:60)
[GIN] 2019/07/18 - 08:47:34 | 204 | 33.322µs | ::1 | OPTIONS /api/post
2019/07/18 08:47:34 [Recovery] 2019/07/18 - 08:47:34 panic recovered:
POST /api/post HTTP/1.1
Host: localhost:4000
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 68
Content-Type: application/json;charset=UTF-8
Origin: http://localhost:3000
Referer: http://localhost:3000/post/finish
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:82 (0x10426f0)
panicmem: panic(memoryError)
/usr/local/go/src/runtime/signal_unix.go:390 (0x104251f)
sigpanic: panicmem()
/Users/jpskgc/go/src/github.com/gin-gonic/gin/context.go:532 (0x17122f5)
(*Context).MultipartForm: return c.Request.MultipartForm, err
/Users/jpskgc/go/src/github.com/gin-gonic/gin/context.go:147 (0x14fdea9)
(*Context).Next: c.handlers[c.index](c)
/Users/jpskgc/go/src/github.com/gin-gonic/gin/recovery.go:83 (0x1511939)
RecoveryWithWriter.func1: c.Next()
/Users/jpskgc/go/src/github.com/gin-gonic/gin/context.go:147 (0x14fdea9)
(*Context).Next: c.handlers[c.index](c)
/Users/jpskgc/go/src/github.com/gin-gonic/gin/logger.go:240 (0x15109e0)
LoggerWithConfig.func1: c.Next()
/Users/jpskgc/go/src/github.com/gin-gonic/gin/context.go:147 (0x14fdea9)
(*Context).Next: c.handlers[c.index](c)
/Users/jpskgc/go/src/github.com/gin-gonic/gin/gin.go:391 (0x1507da9)
(*Engine).handleHTTPRequest: c.Next()
/Users/jpskgc/go/src/github.com/gin-gonic/gin/gin.go:352 (0x150749d)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2774 (0x12e2207)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1878 (0x12dddf0)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1337 (0x1059ed0)
goexit: BYTE $0x90 // NOP
[GIN] 2019/07/18 - 08:47:34 | 500 | 119.560492ms | ::1 | POST /api/post
- frontend: react/axios
- backend: golang/gin
- upload library: dropzone
- storage: amazon s3