英文:
Send zip file as form-data in POST request
问题
我正在尝试在GO中以表单数据的形式将zip文件作为POST请求体发送。所以,它应该是以键值对的格式。在发送未压缩文件时,我能够实现相同的效果。以下是代码片段:
buf := new(bytes.Buffer)
multiPartWriter := multipart.NewWriter(buf)
part, err := multiPartWriter.CreateFormFile("File", fileName)
然而,当涉及到压缩时,我找不到相应的选项:
zipWriter := zip.NewWriter(buf)
zipFile, err := zipWriter.Create(fileName)
与multipart.Writer不同,在zip.Writer的情况下,我找不到以键值对方式创建表单文件的选项。
我该如何在zip中实现这个功能?
代码片段[已更新]:
func SendPostRequest(url string, content []byte, fileName string, doZip bool) (*http.Response, error) {
buf := new(bytes.Buffer)
multiPartWriter := multipart.NewWriter(buf)
part, _ := multiPartWriter.CreateFormFile("File", fileName)
if doZip {
zipWriter := zip.NewWriter(part)
zipFile, _ := zipWriter.Create(fileName)
zipFile.Write(content)
zipWriter.Close()
} else {
part.Write(content)
multiPartWriter.Close()
}
request, _ := http.NewRequest(http.MethodPost, url, buf)
request.Header.Add(constants.Header_content_type_key, multiPartWriter.FormDataContentType())
client := &http.Client{}
response, err := client.Do(request)
return client.Do(request)
}
英文:
I am trying to send a zip file in POST request body as form-data in GO. So, it is supposed to be in a key-value format. I am able to achieve the same while sending an unzipped file. Here is the snippet,
buf := new(bytes.Buffer)
multiPartWriter := multipart.NewWriter(buf)
part, err := multiPartWriter.CreateFormFile("File", fileName)
However, when it comes to zipping it, I am able to find this,
zipWriter := zip.NewWriter(buf)
zipFile, err := zipWriter.Create(fileName)
Unlike multipart.Writer, in case of zip.Writer I can't find any option to create form file in a key-value fashion.
How can I achieve this for zip as well?
Code snippet[updated],
func SendPostRequest(url string, content []byte, fileName string,
doZip bool)(*http.Response, error) {
buf := new(bytes.Buffer)
multiPartWriter := multipart.NewWriter(buf)
part, _ := multiPartWriter.CreateFormFile("File", fileName)
if doZip {
zipWriter := zip.NewWriter(part)
zipFile, _ := zipWriter.Create(fileName)
zipFile.Write(content)
zipWriter.Close()
} else {
part.Write(content)
multiPartWriter.Close()
}
request, _ := http.NewRequest(http.MethodPost, url, buf)
request.Header.Add(constants.Header_content_type_key, multiPartWriter.FormDataContentType())
client := &http.Client{}
response, err := client.Do(request)
return client.Do(request)
}
答案1
得分: 1
通常情况下,我认为你会想使用multiPartWriter.CreatePart(header)
,其中header
的类型是MIMEHeader。CreatePart()
将返回一个io.Writer
- 将其传递给zip.NewWriter()
:
// 假设你已经创建了你的header
w, err := multiPartWriter.CreatePart(header)
if err != nil {
// 处理错误
}
zipWriter := zip.NewWriter(w)
// 向zipWriter添加内容
你可能需要进行一些调整,具体情况可能有所不同。
英文:
Ordinarily, I think you'd want to use multiPartWriter.CreatePart(header)
, where header
is of type MIMEHeader. CreatePart()
will return an io.Writer
- pass that to zip.NewWriter()
:
// Assume you've created your header already
w, err := multiPartWriter.CreatePart(header)
if err != nil {
// do whatever
}
zipWriter := zip.NewWriter(w)
// Add stuff to zipWriter
You might need to play around, YMMV.
答案2
得分: 0
作为解决方案,当进行压缩时,我只对内容字节切片进行压缩,其他部分对于压缩和非压缩的方法都是相同的。以下是代码片段:
func sendPostRequest(url string, content []byte, projectId string, fileName string, fileType string, doZip bool) (*http.Response, error) {
buf := new(bytes.Buffer)
writer := multipart.NewWriter(buf)
part, err := writer.CreateFormFile("File", fileName)
if err != nil {
return nil, errors.New("Invocation of *multipart.Writer.CreateFormFile() failed: " + err.Error())
}
content, err = ZipBytes(fileName, content, doZip)
if err != nil {
return nil, err
}
_, err = part.Write(content)
if err != nil {
return nil, errors.New("Invocation of io.Writer.Write() failed: " + err.Error())
}
if err = writer.Close(); err != nil {
return nil, errors.New("Failed to close *multipart.Writer: " + err.Error())
}
request, err := http.NewRequest(http.MethodPost, url, buf)
if err != nil {
return nil, errors.New("Failed to create request for Validation API multipart file uploading: " + err.Error())
}
request.Header.Add(constants.Header_content_type_key, writer.FormDataContentType())
request.Header.Add(constants.Project_Id_header_str, projectId)
request.Header.Add(constants.File_type_header_str, fileType)
if doZip {
request.Header.Add(constants.IsZipped_header_str, "true")
} else {
request.Header.Add(constants.IsZipped_header_str, "false")
}
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return nil, errors.New("Failed to invoke Validation API: " + err.Error())
} else if !strings.Contains(strconv.Itoa(response.StatusCode), "20") {
respMap, _ := processValidationResponse(response)
message := fmt.Sprintf("Failed to invoke Validation API with HTTP %s : %s", strconv.Itoa(response.StatusCode), respMap["message"])
return nil, errors.New(message)
}
return response, nil
}
func ZipBytes(fileName string, content []byte, doZip bool) ([]byte, error) {
if doZip {
log.Println("Zipped file will be sent for validation")
buf := new(bytes.Buffer)
zipWriter := zip.NewWriter(buf)
zipFile, err := zipWriter.Create(fileName)
if err != nil {
return nil, errors.New("Zip file creation failed: " + err.Error())
}
_, err = zipFile.Write(content)
if err != nil {
return nil, errors.New("Writing to zip file failed: " + err.Error())
}
if err = zipWriter.Close(); err != nil {
return nil, errors.New("Failed to close zip writer: " + err.Error())
}
return buf.Bytes(), nil
} else {
log.Println("Normal file will be sent for validation")
return content, nil
}
}
英文:
As a solution to this one - I am doing a zip of the content byte slice only, when it comes to zipping. Rest are common for both zipped/non-zipped approach. Here are the code snippets,
func sendPostRequest(url string, content []byte, projectId string, fileName string, fileType string, doZip bool) (*http.Response, error) {
buf := new(bytes.Buffer)
writer := multipart.NewWriter(buf)
part, err := writer.CreateFormFile("File", fileName)
if err != nil {
return nil, errors.New("Invocation of *multipart.Writer.CreateFormFile() failed: " + err.Error())
}
content, err = ZipBytes(fileName, content, doZip)
if err != nil {
return nil, err
}
_, err = part.Write(content)
if err != nil {
return nil, errors.New("Invocation of io.Writer.Write() failed: " + err.Error())
}
if err = writer.Close(); err != nil {
return nil, errors.New("Failed to close *multipart.Writer: " + err.Error())
}
request, err := http.NewRequest(http.MethodPost, url, buf)
if err != nil {
return nil, errors.New("Failed to create request for Validation API multipart file uploading: " + err.Error())
}
request.Header.Add(constants.Header_content_type_key, writer.FormDataContentType())
request.Header.Add(constants.Project_Id_header_str, projectId)
request.Header.Add(constants.File_type_header_str, fileType)
if doZip {
request.Header.Add(constants.IsZipped_header_str, "true")
} else {
request.Header.Add(constants.IsZipped_header_str, "false")
}
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return nil, errors.New("Failed to invoke Validation API: " + err.Error())
} else if !strings.Contains(strconv.Itoa(response.StatusCode), "20") {
respMap, _ := processValidationResponse(response)
message := fmt.Sprintf("Failed to invoke Validation API with HTTP %s : %s", strconv.Itoa(response.StatusCode), respMap["message"])
return nil, errors.New(message)
}
return response, nil
}
func ZipBytes(fileName string, content []byte, doZip bool) ([]byte, error) {
if doZip {
log.Println("Zipped file will be sent for validation")
buf := new(bytes.Buffer)
zipWriter := zip.NewWriter(buf)
zipFile, err := zipWriter.Create(fileName)
if err != nil {
return nil, errors.New("Zip file creation failed: " + err.Error())
}
_, err = zipFile.Write(content)
if err != nil {
return nil, errors.New("Writing to zip file failed: " + err.Error())
}
if err = zipWriter.Close(); err != nil {
return nil, errors.New("Failed to close zip writer: " + err.Error())
}
return buf.Bytes(), nil
} else {
log.Println("Normal file will be sent for validation")
return content, nil
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论