Last active
November 24, 2021 02:43
-
-
Save HirbodBehnam/d0344f2377cbcd96bc058f31360a7658 to your computer and use it in GitHub Desktop.
A code to upload multiple files with multipart with small ram usage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io" | |
| "io/ioutil" | |
| "log" | |
| "mime/multipart" | |
| "net/http" | |
| "os" | |
| ) | |
| func main() { | |
| url := "https://postman-echo.com/post" // https://docs.postman-echo.com/?version=latest | |
| params := make(map[string]string) | |
| params["test1"] = "param1" | |
| params["test2"] = "param2" | |
| filename1_field := "file1" | |
| filename1 := "test.txt" | |
| filename2_field := "file2" | |
| filename2 := "file2.txt" // however this file will not be read from disk | |
| dataToSend := []byte("Hello!") // insted, send this from memory | |
| r, w := io.Pipe() // use pipe to transfer the data without high RAM usage | |
| m := multipart.NewWriter(w) // create a multipart structure that will use io.Pipe to write to http request | |
| // writing to pipe must be done inside a goroutine; otherwise the program will panic because of deadlock | |
| go func() { | |
| defer w.Close() // you have to at first close the multipart then the pipe | |
| defer m.Close() // note that this line runes first | |
| // write parameters | |
| for k, v := range params { | |
| _ = m.WriteField(k, v) | |
| } | |
| // send the first file that is present on the disk | |
| part, err := m.CreateFormFile(filename1_field, filename1) | |
| if err != nil{ | |
| log.Fatal(err) | |
| } | |
| file1, _ := os.Open(filename1) // open the file to read from it | |
| io.Copy(part,file1) // copy the file to multipart; The multipart will use io.pipe to write them to the destination; No worries about the RAM, the buffer size is 32KB | |
| file1.Close() | |
| // now upload the second file from memory | |
| part2, err := m.CreateFormFile(filename2_field, filename2) | |
| if err != nil{ | |
| log.Fatal(err) | |
| } | |
| io.Copy(part2,bytes.NewReader(dataToSend)) | |
| }() | |
| req, _ := http.NewRequest("POST", url, r) // as you can see I have passed the pipe reader here | |
| req.Header.Set("Content-Type", m.FormDataContentType()) | |
| resp, err := http.DefaultClient.Do(req) // do the request. The program will stop here until the upload is done | |
| if err != nil{ | |
| log.Fatal(err) | |
| } | |
| data,_ := ioutil.ReadAll(resp.Body) // read the results | |
| fmt.Println(string(data)) // display the results | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
๐