将zip文件作为form-data在POST请求中发送。

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

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的类型是MIMEHeaderCreatePart()将返回一个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
}
}

huangapple
  • 本文由 发表于 2023年2月2日 05:18:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75316296.html
匿名

发表评论

匿名网友

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

确定