使用额外参数实现多部分文件上传
Implementing multipart file upload with extra params
我正在尝试复制以下命令:
curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/HTML/1.7.0"' -F wikitext=%27%27%27Mahikari%27%27%27%20is%20a%20%5B%5BJapan%5D%5Dese%20%5B%5Bnew%20religious%20movement%5D%5D -F body_only=true -F 'https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html'
文件作为 url 带引号的参数传递给 curl
。
原始文件的内容如下(没有尾随 returns):
'''Mahikari''' is a [[Japan]]ese [[new religious movement]]
目前我添加的唯一参数是body_only=true
预期的正确答案是:
<p id="mwAQ"><b id="mwAg">Mahikari</b> is a <a rel="mw:WikiLink" href="./Japan" title="Japan" id="mwAw">Japanese</a> <a rel="mw:WikiLink" href="./New_religious_movement" title="New religious movement" id="mwBA">new religious movement</a></p>
下面的代码没有返回任何东西(甚至没有错误!):
package main
import (
"bytes"
"fmt"
"io"
// "io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
// Creates a new file upload http request with optional extra params
func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
// fileContents, err := ioutil.ReadAll(file)
// if err != nil {
// return nil, err
// }
fi, err := file.Stat()
if err != nil {
return nil, err
}
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile(paramName, fi.Name())
if err != nil {
return nil, err
}
// part.Write(fileContents)
io.Copy(part, file)
for key, val := range params {
_ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {
return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Add("Content-Type", writer.FormDataContentType())
request.Header.Add("Accept", "text/html; charset=utf-8; profile=\"https://www.mediawiki.org/wiki/Specs/HTML/1.7.0\"")
return request, err
}
func transformWikitextToHtml(path string) {
extraParams := map[string]string{
"body_only": "true",
}
request, err := newfileUploadRequest("https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html", extraParams, "file", path)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
} else {
var bodyContent []byte
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
resp.Body.Read(bodyContent)
resp.Body.Close()
fmt.Println(bodyContent)
}
}
func main() {
transformWikitextToHtml("/tmp/2239217")
}
我根据文档和预期设置了 headers。我尝试了一些方法,例如立即读取文件(注释掉),但这没有帮助。我错过了什么?
在您的 CURL 请求中,您将 wikitext
作为字段 (-F wikitext=...
) 发送。
但是,在您的代码中,您将其作为文件部分发送。
如果您将其作为字段发送,它将按您预期的方式工作。
只需将文件内容作为附加字段包含在您的代码中:
func transformWikitextToHtml(path string) {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(err)
}
extraParams := map[string]string{
"body_only": "true",
"wikitext": string(fileBytes),
}
// rest of the code should be as you posted
}
当然,删除 newfileUploadRequest
中与路径和文件参数名称相关的部分,这些不再需要。
此外,在编写响应正文时,您遇到了一个小错误,即使代码已修复,它也不会打印任何内容,因此请将该部分替换为:
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bodyBytes))
完整的工作代码:
package main
import (
"bytes"
"fmt"
"log"
"mime/multipart"
"net/http"
"io/ioutil"
)
// Creates a new file upload http request with optional extra params
func newfileUploadRequest(uri string, params map[string]string) (*http.Request, error) {
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
for key, val := range params {
err := writer.WriteField(key, val)
if err != nil {
log.Fatal(err)
}
}
err := writer.Close()
if err != nil {
return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Add("Content-Type", writer.FormDataContentType())
request.Header.Add("Accept", "text/html; charset=utf-8; profile=\"https://www.mediawiki.org/wiki/Specs/HTML/1.7.0\"")
return request, err
}
func transformWikitextToHtml(path string) {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(err)
}
extraParams := map[string]string{
"body_only": "true",
"wikitext": string(fileBytes),
}
request, err := newfileUploadRequest("https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html", extraParams)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
} else {
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bodyBytes))
}
}
func main() {
transformWikitextToHtml("/tmp/2239217")
}
我正在尝试复制以下命令:
curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/HTML/1.7.0"' -F wikitext=%27%27%27Mahikari%27%27%27%20is%20a%20%5B%5BJapan%5D%5Dese%20%5B%5Bnew%20religious%20movement%5D%5D -F body_only=true -F 'https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html'
文件作为 url 带引号的参数传递给 curl
。
原始文件的内容如下(没有尾随 returns):
'''Mahikari''' is a [[Japan]]ese [[new religious movement]]
目前我添加的唯一参数是body_only=true
预期的正确答案是:
<p id="mwAQ"><b id="mwAg">Mahikari</b> is a <a rel="mw:WikiLink" href="./Japan" title="Japan" id="mwAw">Japanese</a> <a rel="mw:WikiLink" href="./New_religious_movement" title="New religious movement" id="mwBA">new religious movement</a></p>
下面的代码没有返回任何东西(甚至没有错误!):
package main
import (
"bytes"
"fmt"
"io"
// "io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
// Creates a new file upload http request with optional extra params
func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
// fileContents, err := ioutil.ReadAll(file)
// if err != nil {
// return nil, err
// }
fi, err := file.Stat()
if err != nil {
return nil, err
}
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile(paramName, fi.Name())
if err != nil {
return nil, err
}
// part.Write(fileContents)
io.Copy(part, file)
for key, val := range params {
_ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {
return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Add("Content-Type", writer.FormDataContentType())
request.Header.Add("Accept", "text/html; charset=utf-8; profile=\"https://www.mediawiki.org/wiki/Specs/HTML/1.7.0\"")
return request, err
}
func transformWikitextToHtml(path string) {
extraParams := map[string]string{
"body_only": "true",
}
request, err := newfileUploadRequest("https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html", extraParams, "file", path)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
} else {
var bodyContent []byte
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
resp.Body.Read(bodyContent)
resp.Body.Close()
fmt.Println(bodyContent)
}
}
func main() {
transformWikitextToHtml("/tmp/2239217")
}
我根据文档和预期设置了 headers。我尝试了一些方法,例如立即读取文件(注释掉),但这没有帮助。我错过了什么?
在您的 CURL 请求中,您将 wikitext
作为字段 (-F wikitext=...
) 发送。
但是,在您的代码中,您将其作为文件部分发送。
如果您将其作为字段发送,它将按您预期的方式工作。
只需将文件内容作为附加字段包含在您的代码中:
func transformWikitextToHtml(path string) {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(err)
}
extraParams := map[string]string{
"body_only": "true",
"wikitext": string(fileBytes),
}
// rest of the code should be as you posted
}
当然,删除 newfileUploadRequest
中与路径和文件参数名称相关的部分,这些不再需要。
此外,在编写响应正文时,您遇到了一个小错误,即使代码已修复,它也不会打印任何内容,因此请将该部分替换为:
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bodyBytes))
完整的工作代码:
package main
import (
"bytes"
"fmt"
"log"
"mime/multipart"
"net/http"
"io/ioutil"
)
// Creates a new file upload http request with optional extra params
func newfileUploadRequest(uri string, params map[string]string) (*http.Request, error) {
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
for key, val := range params {
err := writer.WriteField(key, val)
if err != nil {
log.Fatal(err)
}
}
err := writer.Close()
if err != nil {
return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Add("Content-Type", writer.FormDataContentType())
request.Header.Add("Accept", "text/html; charset=utf-8; profile=\"https://www.mediawiki.org/wiki/Specs/HTML/1.7.0\"")
return request, err
}
func transformWikitextToHtml(path string) {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(err)
}
extraParams := map[string]string{
"body_only": "true",
"wikitext": string(fileBytes),
}
request, err := newfileUploadRequest("https://en.wikipedia.org/api/rest_v1/transform/wikitext/to/html", extraParams)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
} else {
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bodyBytes))
}
}
func main() {
transformWikitextToHtml("/tmp/2239217")
}