Uplaod большой файл не все в памяти - PullRequest
0 голосов
/ 29 апреля 2020

Я использую для загрузки файлов на сайт с помощью этой команды bash:

cmd2=$(curl -F "$FileField=@$FileName" -F "signature=$Sig" -F "ajax=$Ajax"  -F "params=$Params" "$Url")

Теперь я преобразовал в golang и использую эту функцию:

// Open the file.
file, err := os.Open(k.Path)
if err != nil {
    fmt.Println("Open File", err)
    return
}

// Schedule the file to be closed once
// the function returns.
defer file.Close()

// Create a synchronous in-memory pipe. This pipe will
// allow us to use a Writer as a Reader.
pipeReader, pipeWriter := io.Pipe()

var mpWriter *multipart.Writer

body2 := &bytes.Buffer{}

// Create a goroutine to perform the write since
// the Reader will block until the Writer is closed.
go func() {

    // Create a Reader that writes to the hash what it reads
    // from the file.
    fileReader := io.TeeReader(file, body2)

    // Create the multipart writer to put everything together.
    mpWriter = multipart.NewWriter(pipeWriter)
    fileWriter, err := mpWriter.CreateFormFile(responseObject.FileField, filepath.Base(k.Path))

    // Write the contents of the file to the multipart form.
    _, err = io.Copy(fileWriter, fileReader)
    if err != nil {
        fmt.Println("Write File", err)
        return
    }

    // Add the keys we generated.
    mpWriter.WriteField("ajax", strconv.FormatBool(responseObject.FormData.Ajax))
    mpWriter.WriteField("params", responseObject.FormData.Params)
    mpWriter.WriteField("signature", responseObject.FormData.Signature)

    // Close the Writer which will cause the Reader to unblock.
    defer mpWriter.Close()
    defer pipeWriter.Close()
}()

// Wait until the Writer is closed, then write the
// Pipe to Stdout.
io.Copy(body2, pipeReader)

client := &http.Client{}

// Send post request
req, err := http.NewRequest("POST", responseObject.FormAction, body2)

req.Header.Set("Content-Type", mpWriter.FormDataContentType())

// Submit the request
res, err := client.Do(req)
...

для небольших файлов у меня нет проблем, но когда я пытаюсь загрузить большие файлы, он загружает все файлы в память и программу cra sh.

Я пытаюсь найти решение, но безуспешно, что я могу изменить?

Спасибо

1 Ответ

0 голосов
/ 30 апреля 2020

Вы создаете образ памяти потока, а затем передаете этот образ памяти на сервер. Вместо этого вы должны использовать канал напрямую, чтобы в любой момент времени в памяти находились только небольшие фрагменты большого файла:

req, err := http.NewRequest("POST", responseObject.FormAction, pipeReader)

Не используйте буфер body2.

...