发送已上传的文件

huangapple go评论85阅读模式
英文:

Send uploaded file

问题

我使用echo框架来构建REST API。
我通过HTTP请求接收文件,并且需要通过POST请求将其发送到下一个API服务。
我如何在不存储文件的情况下完成这个操作?

我尝试了以下方法,但感觉不对,因为我在响应中收到了一个错误消息"Could not parse content as FormData"。

func (h *Handler) UploadFile(c echo.Context) error {
    formFile, err := c.FormFile("file")
    if err != nil {
        return err
    }

    file, err := formFile.Open()
    if err != nil {
        return err
    }
    defer file.Close()

    cid, err := h.s.Upload(context.Background(), file)
    if err != nil {
        return err
    }

    return c.String(http.StatusOK, "Ok")
}

func (s *Storage) Upload(ctx context.Context, file io.Reader) (cid.Cid, error) {
    req, err := http.NewRequest(http.MethodPost, s.config.endpoint+"/upload", file)
    if err != nil {
        return cid.Undef, err
    }
    req.Header.Set("accept", "application/json")
    req.Header.Set("Content-Type", "multipart/form-data")
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.config.token))
    res, err := s.config.hc.Do(req)
    if err != nil {
        return cid.Undef, err
    }
    d := json.NewDecoder(res.Body)
    if res.StatusCode != 200 {
        return cid.Undef, fmt.Errorf("unexpected response status: %d", res.StatusCode)
    }
    var out struct {
        Cid string `json:"cid"`
    }
    err = d.Decode(&out)
    if err != nil {
        return cid.Undef, err
    }
    return cid.Parse(out.Cid)
}
英文:

I use echo framework for building REST API.
I receive file via http request and i need to send it to the next API service by post request.
How i can do this without storing file?

I've tried this way, but it doesn't feel right, because i have an error in response "Could not parse content as FormData"

func (h *Handler) UploadFile(c echo.Context) error {
	formFile, err := c.FormFile("file")
	if err != nil {
		return err
	}

	file, err := formFile.Open()
	if err != nil {
		return err
	}
	defer file.Close()

	cid, err := h.s.Upload(context.Background(), file)
	if err != nil {
		return err
	}

	return c.String(http.StatusOK, "Ok")

}

func (s *Storage) Upload(ctx context.Context, file io.Reader) (cid.Cid, error) {
	req, err := http.NewRequest(http.MethodPost, s.config.endpoint+"/upload", file)
	if err != nil {
		return cid.Undef, err
	}
	req.Header.Set("accept", "application/json")
	req.Header.Set("Content-Type", "multipart/form-data")
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.config.token))
	res, err := s.config.hc.Do(req)
	if err != nil {
		return cid.Undef, err
	}
	d := json.NewDecoder(res.Body)
	if res.StatusCode != 200 {
		return cid.Undef, fmt.Errorf("unexpected response status: %d", res.StatusCode)
	}
	var out struct {
		Cid string `json:"cid"`
	}
	err = d.Decode(&out)
	if err != nil {
		return cid.Undef, err
	}
	return cid.Parse(out.Cid)
}

答案1

得分: 1

这里 是解决方案。
感谢 Vlad Vladov

func (s *Storage) Upload(ctx context.Context, file multipart.File, fileHeader *multipart.FileHeader) (cid.Cid, error) {
	rCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	buf := new(bytes.Buffer)
	writer := multipart.NewWriter(buf)

	part, err := writer.CreateFormFile("file", fileHeader.Filename)
	if err != nil {
		return cid.Undef, err
	}

	b, err := ioutil.ReadAll(file)

	if err != nil {
		return cid.Undef, err
	}

	part.Write(b)
	writer.Close()
	req, err := http.NewRequestWithContext(rCtx, http.MethodPost, s.config.endpoint+"/upload", buf)
	if err != nil {
		return cid.Undef, err
	}

	req.Header.Set("Content-Type", writer.FormDataContentType())
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.config.token))
	req.Header.Set("X-Client", "web3.storage/go")

	res, err := s.config.hc.Do(req)
	if err != nil {
		return cid.Undef, err
	}

	d := json.NewDecoder(res.Body)
	if res.StatusCode != 200 {
		var out responseError
		d.Decode(&out)
		log.Error(out)
		return cid.Undef, fmt.Errorf("unexpected response status: %d", res.StatusCode)
	}
	var out struct {
		Cid string `json:"cid"`
	}
	err = d.Decode(&out)
	if err != nil {
		return cid.Undef, err
	}
	return cid.Parse(out.Cid)
}
英文:

Here is the solution.
Thanks Vlad Vladov.

func (s *Storage) Upload(ctx context.Context, file multipart.File, fileHeader *multipart.FileHeader) (cid.Cid, error) {
	rCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	buf := new(bytes.Buffer)
	writer := multipart.NewWriter(buf)

	part, err := writer.CreateFormFile("file", fileHeader.Filename)
	if err != nil {
		return cid.Undef, err
	}

	b, err := ioutil.ReadAll(file)

	if err != nil {
		return cid.Undef, err
	}

	part.Write(b)
	writer.Close()
	req, err := http.NewRequestWithContext(rCtx, http.MethodPost, s.config.endpoint+"/upload", buf)
	if err != nil {
		return cid.Undef, err
	}

	req.Header.Set("Content-Type", writer.FormDataContentType())
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.config.token))
	req.Header.Set("X-Client", "web3.storage/go")

	res, err := s.config.hc.Do(req)
	if err != nil {
		return cid.Undef, err
	}

	d := json.NewDecoder(res.Body)
	if res.StatusCode != 200 {
		var out responseError
		d.Decode(&out)
		log.Error(out)
		return cid.Undef, fmt.Errorf("unexpected response status: %d", res.StatusCode)
	}
	var out struct {
		Cid string `json:"cid"`
	}
	err = d.Decode(&out)
	if err != nil {
		return cid.Undef, err
	}
	return cid.Parse(out.Cid)
}

huangapple
  • 本文由 发表于 2023年3月20日 19:40:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75789829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定