Реализация многочастной загрузки файла с дополнительными параметрами - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь повторить следующую команду:

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.

Содержимое исходного файла задается как(без конечных возвратов):

'''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")
}

Я установил заголовки в соответствии с документацией и тем, что ожидается.Я попробовал несколько вещей, как чтение файла сразу (закомментировано), но это не помогло.Чего мне не хватает?

1 Ответ

0 голосов
/ 12 июня 2018

В своем запросе 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")
}
...