So I spent some time trying to code up a little upload function to
send files up to a server. The server expects a form upload, like you
would get from using this html in the browser:
<form method='POST' enctype='multipart/form-data'
action='
http://localhost:8888'>
File to upload: <input type=file name=upfile><br>
<br>
<input type=submit value=Press> to upload the file!
</form>
I couldn't find a pre-packaged way to do this, so I came up with the
following simple approach:
package main
import (
"fmt"
"net/http"
"mime/multipart"
"bytes"
"os"
"io"
)
func main() {
target_url := "
http://localhost:8888/"
body_buf := bytes.NewBufferString("")
body_writer := multipart.NewWriter(body_buf)
filename := "/path/to/file.rtf"
file_writer, err := body_writer.CreateFormFile("upfile", filename)
if err != nil {
fmt.Println("error writing to buffer")
return
}
fh, err := os.Open(filename)
if err != nil {
fmt.Println("error opening file")
return
}
io.Copy(file_writer, fh)
body_writer.Close()
http.Post(target_url, "bad/mime", body_buf)
}
-------------
Aside from not doing mimetype setting -- this "works". My fear
however is that for large files io.Copy is going to write the whole
contents of the file into the buffer, before I can send it with
http.Post. For small files this isn't a concern. But for large files
(4GB+ lets say) thats a bunch of memory. I'm wondering if there is a
way to have a buffer type that has a notion of "maximum size before I
start using disk" so that for large files it would store the buffer to
disk and not chew memory. I feel like there should be some way (that
i'm missing) to do this using a bufio or something, but I wasn't
coming up with anything. Its unfortunate that I have to copy the file
to the buffer for the request, and then send the whole request to the
wire. Perhaps I should create a reader/writer where you can "append"
a reader to a set of readers -- and when one returns EOF it starts
reading the next.... So you could append a file, to a buffer without
reading the contents -- until you're actually "reading" the whole
thing to copy to the socket.
Anyone have experience with this?
-James-