I want to upload a file with the content type set to application/octet-stream and the binary data of the file in the request body. How would I do this in golang, here is my starting code:
package main import ( "fmt" "log" "net/http" "net/http/httputil" "os" ) func main() { file, err := os.Open("file.pdf") if err != nil { log.Fatalln(err) } req, err := http.NewRequest("POST", fmt.Sprintf("https://example.com/upload"), nil) req.Header.Add("Content-Type", "application/octet-stream") if err != nil { log.Fatalln(err) } client := &http.Client{ Transport: &http.Transport{ DisableCompression: true, }, } resp, err := client.Do(req) if err != nil { log.Fatalln(err) } defer resp.Body.Close() reqDump, err := httputil.DumpRequest(req, true) if err != nil { log.Fatalln(err) } fmt.Println(reqDump) }
I put together an answer that may help you solve your problem. All code belongs to the main.go
file and is just for demonstration. It has two main parts: handler
and main
functions. Let's start with the handler.
func handlefile(w http.responsewriter, r *http.request) { if r.method != http.methodpost { w.writeheader(http.statusmethodnotallowed) return } fmt.println("handlefile") data, err := io.readall(r.body) if err != nil { panic(err) } defer r.body.close() w.write(data) }
Here, I'm just relying on what you're using (go standard libraries only: http
, io
and fmt
packages). We just need to write the incoming payload read from the http request to the response stream.
func main() { r := http.NewServeMux() r.HandleFunc("/example", HandleFile) srv := http.Server{ Addr: ":8000", Handler: r, } var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() if err := srv.ListenAndServe(); err != nil { fmt.Println(err.Error()) } }() file, err := os.Open("file.txt") if err != nil { panic(err) } defer file.Close() req, err := http.NewRequest(http.MethodPost, "http://localhost:8000/example", file) if err != nil { panic(err) } req.Header.Set("Content-Type", "application/octet-stream") client := &http.Client{ Transport: &http.Transport{ DisableCompression: true, }, } res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } fmt.Println(string(data)) srv.Shutdown(context.Background()) wg.Wait() }
In contrast, the main
function has more logic to deal with. Let’s review them in the list:
/example
endpoint using the handlefile
handler we created earlier. sync.waitgroup
to run the server in a separate goroutine. Thanks to this, the server is up and running, but we can continue our program and send http requests within it. file.txt
in our example). We set the content-type
header to application/octet-stream
and pass the file handle to the newrequest
function. wg.wait
method to tell the waitgroup to wait for all goroutines. The code written here can definitely be improved. Anyway, just for demonstration, I prefer to keep it as close to the original file as possible to give you a better understanding of how to publish binaries on an http server and how to run the same program both client and server. If there is anything unclear, please tell me, thank you!
The above is the detailed content of Post binary data (application/octet stream). For more information, please follow other related articles on the PHP Chinese website!