前提・実現したいこと
大量のテキストファイル(1万ファイル以上)を POST したい。
エラーメッセージ
fatal: error: Post "http://xxx.xxx.xxx.xxx:xxxx/upload": dial tcp xxx.xxx.xxx.xxx:xxxx: i/o timeout<nil>
該当のソースコード
うまくいくパターン
go
1func main(){ 2 ary := ["/root/a/a.txt","/root/b/b.txt","/root/c/c.txt",...] // アップロード対象のファイルパスが大量に入っている配列 3 4 for _,v := range ary { 5 postFile(v, "http://xxx.xxx.xxx.xxx:xxxx/upload") 6 } 7} 8 9func postFile(filename string, targetUrl string) error { 10 bodyBuf := &bytes.Buffer{} 11 bodyWriter := multipart.NewWriter(bodyBuf) 12 13 //キーとなる操作 14 fileWriter, err := bodyWriter.CreateFormFile("file-text", filename) 15 if err != nil { 16 fmt.Println("error writing to buffer") 17 return err 18 } 19 20 //ファイルハンドル操作をオープンする 21 fh, err := os.Open(filename) 22 if err != nil { 23 fmt.Println("error opening file") 24 return err 25 } 26 defer fh.Close() 27 28 //iocopy 29 _, err = io.Copy(fileWriter, fh) 30 if err != nil { 31 return err 32 } 33 34 contentType := bodyWriter.FormDataContentType() 35 bodyWriter.Close() 36 37 resp, err := http.Post(targetUrl, contentType, bodyBuf) 38 if err != nil { 39 return err 40 } 41 defer resp.Body.Close() 42 resp_body, err := ioutil.ReadAll(resp.Body) 43 if err != nil { 44 return err 45 } 46 fmt.Println(resp.Status) 47 fmt.Println(string(resp_body)) 48 return nil 49} 50
エラーが出るパターン
go
1func main (){ 2 ary := ["/root/a/a.txt","/root/b/b.txt","/root/c/c.txt",...] // アップロード対象のファイルパスが大量に入っている配列 3 file_upload(ary) 4} 5func file_upload(file_paths []string) { 6 for _, file_path := range file_paths { 7 8 var buf bytes.Buffer 9 w := multipart.NewWriter(&buf) 10 11 f, err := os.Open(file_path) 12 if err != nil { 13 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 14 } 15 defer f.Close() 16 fw, err := w.CreateFormFile("file-text", file_path) 17 if err != nil { 18 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 19 } 20 _, err = io.Copy(fw, f) 21 if err != nil { 22 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 23 } 24 w.Close() 25 req, err := http.NewRequest("POST", "http://xxx.xxx.xxx.xxx:xxxx/upload", &buf) 26 if err != nil { 27 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 28 } 29 req.Header.Set("Authorization", "Bearer YYYY") 30 req.Header.Set("Content-Type", w.FormDataContentType()) 31 32 resp, err := http.DefaultClient.Do(req) 33 defer resp.Body.Close() 34 time.Sleep(time.Second * 1) 35 if err != nil { 36 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 37 } 38 fmt.Println(resp) 39 } 40} 41
希望
file_upload
関数の書き方でPOSTしたい(AuthorizationのBearerを使いたいたいめ)のですが、上記の io エラーが出てしまっています。(5ファイル~20ファイル程はきちんとアップロードされ、そのあと詰まった感じになり上記エラーが発生。早すぎるから問題なのかな?思い、送信処理時にsleepを毎回1秒ほどいれてみたが結果は変わらず。)
ioエラーを出さずに、POST(AuthorizationのBearer利用)できる方法がありましたらご教示いただけませんでしょうか?
うまくいくパターンの書き方ですと、ヘッダーの追加が不可能なため何かいい手がありましたら幸いです。
補足情報(FW/ツールのバージョンなど)
Ubuntu18.04
go version go1.15.6 linux/amd64
#追記
頂いたアドバイスを元に修正したバージョン1(func(){}()を追記)
go
1func main (){ 2 ary := ["/root/a/a.txt","/root/b/b.txt","/root/c/c.txt",...] // アップロード対象のファイルパスが大量に入っている配列 3 file_upload(ary) 4} 5func file_upload(file_paths []string) { 6 for _, file_path := range file_paths { 7 func () { 8 var buf bytes.Buffer 9 w := multipart.NewWriter(&buf) 10 11 f, err := os.Open(file_path) 12 if err != nil { 13 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 14 } 15 defer f.Close() 16 fw, err := w.CreateFormFile("file-text", file_path) 17 if err != nil { 18 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 19 } 20 _, err = io.Copy(fw, f) 21 if err != nil { 22 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 23 } 24 w.Close() 25 req, err := http.NewRequest("POST", "http://xxx.xxx.xxx.xxx:xxxx/upload", &buf) 26 if err != nil { 27 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 28 } 29 req.Header.Set("Authorization", "Bearer YYYY") 30 req.Header.Set("Content-Type", w.FormDataContentType()) 31 32 resp, err := http.DefaultClient.Do(req) 33 defer resp.Body.Close() 34 time.Sleep(time.Second * 1) 35 if err != nil { 36 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 37 } 38 fmt.Println(resp) 39 }() 40 } 41}
頂いたアドバイスを元に修正したバージョン(for文の中で関数を回す)
go
1func main (){ 2 ary := ["/root/a/a.txt","/root/b/b.txt","/root/c/c.txt",...] // アップロード対象のファイルパスが大量に入っている配列 3 for _,file_path := range file_paths{ 4 file_upload(file_path) 5 } 6} 7func file_upload(file_path string) { 8 9 var buf bytes.Buffer 10 w := multipart.NewWriter(&buf) 11 12 f, err := os.Open(file_path) 13 if err != nil { 14 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 15 } 16 defer f.Close() 17 fw, err := w.CreateFormFile("file-text", file_path) 18 if err != nil { 19 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 20 } 21 _, err = io.Copy(fw, f) 22 if err != nil { 23 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 24 } 25 w.Close() 26 req, err := http.NewRequest("POST", "http://xxx.xxx.xxx.xxx:xxxx/upload", &buf) 27 if err != nil { 28 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 29 } 30 req.Header.Set("Authorization", "Bearer YYYY") 31 req.Header.Set("Content-Type", w.FormDataContentType()) 32 33 resp, err := http.DefaultClient.Do(req) 34 defer resp.Body.Close() 35 time.Sleep(time.Second * 1) 36 if err != nil { 37 fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error()) 38 } 39 fmt.Println(resp) 40}
ともに詰まってしまい、同じエラーメッセージがクライアント側で表示されます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/30 14:06
2020/12/30 14:16
2020/12/30 14:17
2020/12/30 14:17
2020/12/30 17:23
2021/01/03 18:33
2021/01/03 19:14
2021/01/04 18:51