douli4337 2019-07-18 01:06
浏览 190
已采纳

如何通过react / axios和golang / gin将图像上传到S3

I want to make functionality to post image to S3 in following steps.

  1. user upload image(s) on the screen.
  2. image files are sent to server after submitting
  3. 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
  • 写回答

1条回答

      报告相同问题?

      相关推荐 更多相似问题

      悬赏问题

      • ¥15 求用C语言数组编程(需要完整且正确的程序)
      • ¥15 前端和swagger调导出接口乱码
      • ¥20 有没有ftps服务器可以使用公钥登录的?
      • ¥20 Ffmpeg代码层面如何实现视频陪速播放
      • ¥15 用python定义函数实现功能使用列表中动漫信息
      • ¥15 unity 使用 Vuforia 导入Model target 成功后database下拉菜单不显示导入的内容
      • ¥15 VBA跨工作簿获取目标工作簿内已有数据的列号
      • ¥30 Dijkstra‘s 最短路径
      • ¥15 在线教育培训平台,主要以点播视频和在线练习测试为主,除将视频做切片外,有其他哪种方式降低流量?(关键词-带宽速率)
      • ¥20 用c语音或c++实现银行叫号系统