gpt4 book ai didi

curl - 使用 GoLang 通过curl 发送多部分请求

转载 作者:行者123 更新时间:2023-12-03 02:40:12 24 4
gpt4 key购买 nike

我想将下面的代码转换为golang。

curl -X POST
'https://api.documo.com/v1/fax/send' \
-H 'Authorization: Basic YOUR_API_KEY' \
-H 'content-type: multipart/form-data' \
-F 'recipientFax=12345678900' \
-F 'coverPage=false' \
-F 'recipientName=John' \
-F 'subject=test' \
-F 'notes=test' \
-F '=@/home/user/Documents/Sample.pdf'

请帮忙

下面是我尝试过的代码。

func SendFaxDocumo(files []*multipart.FileHeader, params map[string]string) {

request, err := SendMultipartRequest("https://api.documo.com/v1/fax/send", params, files)
if err != nil {
fmt.Println(err.Error())

}
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
fmt.Println(err.Error())
} else {
body := &bytes.Buffer{}
_, err := body.ReadFrom(resp.Body)
if err != nil {
fmt.Println(err.Error())
}
resp.Body.Close()
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
fmt.Println(body)
}
}

func SendMultipartRequest(uri string, params map[string]string, files []*multipart.FileHeader) (*http.Request, error) {

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

for i, _ := range files {
// string_index := strconv.Itoa(i)
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Println(err)
}

doc , err := ioutil.ReadAll(file)
if err != nil {
fmt.Println(err,980)
}

part, err := writer.CreateFormFile("file",files[i].Filename)

if err != nil {
fmt.Println(err)
}

part.Write([]byte(string(doc)))
if _, err = io.Copy(part, file); err != nil {
fmt.Println(err)
}

if err != nil {
fmt.Println(err)
}
}

for key, val := range params {
_ = writer.WriteField(key, val)
}

err := writer.Close()
if err != nil {
return nil, err
}

req, err := http.NewRequest("POST", uri, body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Basic my_key")

return req, err
}

我收到的错误如下:{“error”:{“name”:“错误”,“message”:“不允许文件扩展名。允许的格式:tiff,gif,png,jpeg,pdf,doc,xls,ppt,pcl,eps,ps,txt ,rtf,xml,fxc,docx,pptx,xlsx"}}

这是从请求的 url 获得的响应,即使我正在通过 pdf 进行尝试。

最佳答案

我刚刚花了几天时间研究同样的问题。使用后httputil.DumpRequest为了查看我实际传递给 Documo 的数据,我发现文件字段的内容类型 header 设置为 Content-Type: application/octet-stream 。这是由 CreateFormFile 设置的你正在使用的方法。请参阅multipart pkg获取源代码。

octet-stream子类型用作二进制文件或需要在应用程序中打开的文件的默认值。请参阅MDN , IANA ,或this awesome explanation .

据我了解,问题在于Documo 希望我们明确告诉他们我们向他们发送的文件类型,以便他们知道如何处理渲染。所以对于我来说,octet-stream没有告诉他们任何事情。将文件内容类型切换为 application/pdf成功了。

解决方案

而不是打电话writer.CreateFormField ,我基本上是从CreateFormFile的源码中复制了三行并硬编码 Content-Type标题为 application/pdf而不是application/octet-stream (注意:我的服务目前仅处理 PDF,因此如果您的文件类型不同,您可能需要对此进行调整)。

代码:


func SendMultipartRequest(uri string, params map[string]string, files []*multipart.FileHeader) (*http.Request, error) {

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

for i, _ := range files {
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Println(err)
}

//////////////////////////////////////////////////////
// replace create CreateFormFile with this
h := make(textproto.MIMEHeader) // import "net/textproto"
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename="%s"`, files[i].Filename)
h.Set("Content-Type", "application/pdf") // this is where you'll set your document type(s)
fileWriter, err := form.CreatePart(h)
///////////////////////////////////////////////////////

if err != nil {
fmt.Println(err)
}

if _, err = io.Copy(fileWriter, file); err != nil {
fmt.Println(err)
}

if err != nil {
fmt.Println(err)
}
}

for key, val := range params {
_ = writer.WriteField(key, val)
}

err := writer.Close()
if err != nil {
return nil, err
}

req, err := http.NewRequest("POST", uri, body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Basic my_key")

return req, err
}

这不是最性感的解决方案,但我现在终于能够通过 Documo 发送完整的文档了。

希望这有帮助。

关于curl - 使用 GoLang 通过curl 发送多部分请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48126954/

24 4 0
文章推荐: svn - 将 TortoiseMerge 设置为 SVN 的外部合并工具?
文章推荐: flutter - 如何保存 List 并使用 Hive 检索?