英文:
Forwarding a file upload
问题
我正在使用Go语言编写一个API端点,该端点将接受上传的文件并立即转发到另一个API。我不想将文件写入任何地方的磁盘,但我也不确定将文件临时存储在内存中的方式是否正确。我找到的所有示例都涉及将文件保存到磁盘上。我在下面发布了我的代码。我从第二个API收到的响应是我未能上传文件,但我可以看到它接收到了"userID"字段。请问有人能指出我做错了什么,并可能建议这是否是最佳方法?
路由处理程序
func (r *Routes) forwardFile(w http.ResponseWriter, req *http.Request){
parameters := mux.Vars(req)
userID := parameters["userID"]
const maxFileSize = 1 * 1024 * 1024 // 1MB
// 将上传的文件读入内存
req.ParseMultipartForm(maxFileSize)
file, fileHeader, err := req.FormFile("fileUpload")
if err != nil {
encodeResponse(w, req, response{obj: nil, err: err})
return
}
defer file.Close()
success, err := service.DoForwardFile(userID, file, fileHeader)
encodeResponse(w, req, response{obj: success, err: err})
}
服务处理程序
func (b *base) DoForwardFile(userID int, file multipart.File, fileHeader *multipart.FileHeader) (FileForwardedResponse, error) {
// 开始构建转发文件的请求
var resp *http.Response
defer func() {
if resp != nil {
resp.Body.Close()
}
reportStat.Complete(0)
}()
// 构建表单体
body := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(body)
// 添加表单字段
bodyWriter.WriteField("userID", strconv.Itoa(userID))
// 将文件添加到表单体中
fileWriter, err := bodyWriter.CreateFormFile("fileUpload", fileHeader.Filename)
if err != nil {
return FileForwardedResponse{}, err
}
// 将文件复制到fileWriter中
_, err = io.Copy(fileWriter, file)
if err != nil {
return FileForwardedResponse{}, err
}
// 关闭表单体写入器
bodyWriter.Close()
// 构建请求URL
apiURL := fmt.Sprintf("%s/v2/users/%d/files", config.APIURL, userID)
// 发送请求
client := &http.Client{Timeout: time.Second * 10}
req, err := http.NewRequest("POST", apiURL, body)
resp, err = client.Do(req)
// ...
}
以上是你提供的代码的翻译。如果你有任何问题,请随时提问。
英文:
I'm working on an api endpoint in go that will accept an upload and then immediately forward to another API. I don't want to write the file to disk anywhere, but I'm not sure storing the file temporarily in memory the way I have is correct either. All the examples that I can find deal with saving the file to disk. I've posted what I'm doing below. The response I get back from the second API is that I failed to post a file, but I can see that it is receiving the "userID" field. Can someone please point out what I'm doing wrong as well as possibly advise if this is the best way to go about this?
Route Handler
func (r *Routes) forwardFile(w http.ResponseWriter, req *http.Request){
parameters := mux.Vars(req)
userID := parameters["userID"]
const maxFileSize = 1 * 1024 * 1024 // 1MB
// pull in the uploaded file into memory
req.ParseMultipartForm(maxFileSize)
file, fileHeader, err := req.FormFile("fileUpload")
if err != nil {
encodeResponse(w, req, response{obj: nil, err: err})
return
}
defer file.Close()
success, err := service.DoForwardFile(userID, file, fileHeader)
encodeResponse(w, req, response{obj: success, err: err})
}
Service Handler
func (b *base) DoForwardFile(userID int, file multipart.File, fileHeader *multipart.FileHeader) (FileForwardedResponse, error) {
// start building our request to forward the file
var resp *http.Response
defer func() {
if resp != nil {
resp.Body.Close()
}
reportStat.Complete(0)
}()
// build a form body
body := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(body)
// add form fields
bodyWriter.WriteField("userID", userID)
// add a form file to the body
fileWriter, err := bodyWriter.CreateFormFile("fileUpload", fileHeader.Filename)
if err != nil {
return FileForwardedResponse{}, err
}
// copy the file into the fileWriter
_, err = io.Copy(fileWriter, file)
if err != nil {
return FileForwardedResponse{}, err
}
// Close the body writer
bodyWriter.Close()
// build request url
apiURL := fmt.Sprintf("%s/v2/users/%d/files", config.APIURL, userID)
// send request
client := &http.Client{Timeout: time.Second * 10}
req, err := http.NewRequest("POST", apiURL, body)
resp, err = client.Do(req)
...
}
答案1
得分: 1
你没有为请求设置Content-Type
。即使标头自动设置为multipart/form-data
,也缺少数据边界。
req, err := http.NewRequest("POST", uri, body)
if err != nil {
return FileForwardedResponse{}, err
}
req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
...
你需要在请求中设置Content-Type
为bodyWriter.FormDataContentType()
。
英文:
You're not setting the Content-Type
for the request. Even if the header gets set automatically to multipart/form-data
, it's missing the data boundary.
req, err := http.NewRequest("POST", uri, body)
if err != nil {
return FileForwardedResponse{}, err
}
req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论