跳转至

文件上传

如何让启动器支持文件上传的 Restful API?

概述#

gRPC 没有给我们提供一个简单文件上传 API,或者说通过 grpc-gateway on GRPC,我们无法直接实现简单文件上传的功能。

grpc-gateway 已经支持了该功能。

快速开始#

  • 安装
$ go get github.com/rookie-ninja/rk-boot/v2
$ go get github.com/rookie-ninja/rk-grpc/v2

1.创建 boot.yaml#

---
grpc:
  - name: greeter
    port: 8080
#   gwPort: 8081                  # 可选项,如果不指定,会使用与 port 一样的端口
    enabled: true
    enableRkGwOption: true

2.创建 main.go#

package main

import (
  "context"
  "fmt"
  "github.com/rookie-ninja/rk-boot/v2"
  "github.com/rookie-ninja/rk-grpc/v2/boot"
  "net/http"
)

func main() {
  // Create a new boot instance.
  boot := rkboot.NewBoot()

  // Bootstrap
  boot.Bootstrap(context.Background())

  // Get grpc entry with name
  grpcEntry := rkgrpc.GetGrpcEntry("greeter")

  // Attachment upload from http/s handled manually
  grpcEntry.GwMux.HandlePath("POST", "/v1/files", handleBinaryFileUpload)

  // Wait for shutdown sig
  boot.WaitForShutdownSig(context.Background())
}

func handleBinaryFileUpload(w http.ResponseWriter, req *http.Request, params map[string]string) {
  err := req.ParseForm()
  if err != nil {
    http.Error(w, fmt.Sprintf("failed to parse form: %s", err.Error()), http.StatusBadRequest)
    return
  }

  f, header, err := req.FormFile("attachment")
  if err != nil {
    http.Error(w, fmt.Sprintf("failed to get file 'attachment': %s", err.Error()), http.StatusBadRequest)
    return
  }
  defer f.Close()

  fmt.Println(header)

  //
  // Now do something with the io.Reader in `f`, i.e. read it into a buffer or stream it to a gRPC client side stream.
  // Also `header` will contain the filename, size etc of the original file.
  //
}

3.验证#

$ curl -X POST -F "attachment=@xxx.txt" localhost:8080/v1/files

Cheers#