Skip to content

Instantly share code, notes, and snippets.

@schollz
Last active July 30, 2023 00:19
Show Gist options
  • Save schollz/f25d77afc9130b72390748bdbce0d9a3 to your computer and use it in GitHub Desktop.
Save schollz/f25d77afc9130b72390748bdbce0d9a3 to your computer and use it in GitHub Desktop.
Go upload/recieve files via POST
#! /bin/bash
for n in {1..100}; do
dd if=/dev/urandom of=file$( printf %d "$n" ).bin bs=1 count=$(( RANDOM + 1024 ))
done
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
// Set a lower memory limit for multipart forms (default is 32 MiB)
// router.MaxMultipartMemory = 8 << 20 // 8 MiB
router.Static("/file", "saved")
router.POST("/many", func(c *gin.Context) {
// Multipart form
form, _ := c.MultipartForm()
files := form.File["file"]
for _, file := range files {
log.Println(file.Filename)
err := c.SaveUploadedFile(file, "saved/"+file.Filename)
if err != nil {
log.Fatal(err)
}
}
fmt.Println(c.PostForm("key"))
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
router.POST("/one", func(c *gin.Context) {
// single file
file, err := c.FormFile("file")
if err != nil {
log.Fatal(err)
}
log.Println(file.Filename)
err = c.SaveUploadedFile(file, "saved/"+file.Filename)
if err != nil {
log.Fatal(err)
}
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8062")
}
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"strings"
)
func main() {
// err := Upload("http://localhost:8002/one", "main.go")
// if err != nil {
// panic(err)
// }
// err := UploadTwo()
// if err != nil {
// panic(err)
// }
downloadFromUrl("http://localhost:8062/file/file1.bin")
}
func downloadFromUrl(url string) {
tokens := strings.Split(url, "/")
fileName := tokens[len(tokens)-1]
fmt.Println("Downloading", url, "to", fileName)
// TODO: check file existence first with io.IsExist
output, err := os.Create(fileName)
if err != nil {
fmt.Println("Error while creating", fileName, "-", err)
return
}
defer output.Close()
response, err := http.Get(url)
if err != nil {
fmt.Println("Error while downloading", url, "-", err)
return
}
defer response.Body.Close()
n, err := io.Copy(output, response.Body)
if err != nil {
fmt.Println("Error while downloading", url, "-", err)
return
}
fmt.Println(n, "bytes downloaded.")
}
func Upload(url, file string) (err error) {
// Prepare a form that you will submit to that URL.
var b bytes.Buffer
w := multipart.NewWriter(&b)
// Add your image file
f, err := os.Open(file)
if err != nil {
return
}
defer f.Close()
fw, err := w.CreateFormFile("file", file)
if err != nil {
return
}
if _, err = io.Copy(fw, f); err != nil {
return
}
// Add the other fields
if fw, err = w.CreateFormField("key"); err != nil {
return
}
if _, err = fw.Write([]byte("KEY")); err != nil {
return
}
// Don't forget to close the multipart writer.
// If you don't close it, your request will be missing the terminating boundary.
w.Close()
// Now that you have a form, you can submit it to your handler.
req, err := http.NewRequest("POST", url, &b)
if err != nil {
return
}
// Don't forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
// Submit the request
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return
}
// Check the response
if res.StatusCode != http.StatusOK {
err = fmt.Errorf("bad status: %s", res.Status)
}
return
}
func UploadTwo() (err error) {
url := "http://localhost:8062/many"
// Prepare a form that you will submit to that URL.
var b bytes.Buffer
w := multipart.NewWriter(&b)
for i := 1; i <= 100; i++ {
fname := fmt.Sprintf("file%d.bin", i)
fw, err2 := w.CreateFormFile("file", fname)
if err2 != nil {
err = err2
return
}
f, err2 := os.Open(fname)
if err2 != nil {
err = err2
return
}
if _, err2 = io.Copy(fw, f); err2 != nil {
err = err2
return
}
f.Close()
}
// Add the other fields
fw, err2 := w.CreateFormField("key")
if err2 != nil {
err = err2
return
}
if _, err2 = fw.Write([]byte("KEY")); err2 != nil {
err = err2
return
}
// Don't forget to close the multipart writer.
// If you don't close it, your request will be missing the terminating boundary.
w.Close()
// Now that you have a form, you can submit it to your handler.
req, err := http.NewRequest("POST", url, &b)
if err != nil {
return
}
// Don't forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
// Submit the request
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return
}
// Check the response
if res.StatusCode != http.StatusOK {
err = fmt.Errorf("bad status: %s", res.Status)
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment