-
Notifications
You must be signed in to change notification settings - Fork 712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Big file upload #133
Comments
@lacravate Yes I believe. Please pick your choice, these methods accepts |
Thanks a lot for the very fast answer. I should have said i am close to an absolute beginner in go (but not at all in development). I tried SetFileReader, with an io.Pipe() though, before asking, but didn't get the expected result. I suppose your answer tells me i muste persevere... Thanks again, cheers. |
@lacravate You're welcome. I happened to be online. Will be heading to bed soon.
Please let me know how it goes. I will check this thread tomorrow. |
Good morning. i tried this (dead simple) : package main
import (
"os"
"gopkg.in/resty.v1"
)
func main() {
f, err := os.Open("my_movie.mp4")
if err != nil { panic(err) }
defer f.Close()
rest := resty.R().SetFileReader("paramName", "my_movie.mp4", f)
resp, err := rest.Post("http://myhost:4001/my_endpoint")
if resp.StatusCode() != 200 { panic(err) }
} -- file name, params, endpoints, obviously changed but it compiles and uploads the file. Out of luck, and out of my league. For the time being. Cheers ! |
@lacravate Thank you, sorry to hear that. Let me check the request flow and get back to you. |
Thanks again. Most sincerely. In that kind of circumstances, i am generally the one at fault. But even that would be a plus to know : i need something to be sure of, a firm ground, to mend my code, even if that sure is thing is that i s... at Go for the moment. Cheers ! |
@lacravate I had a look, there is buffer in-between before the actual request is fired. I have questions for you-
For a first one - Multipart data - Parts and boundary values are involved. Its bit complex for bringing generalized solution in resty. Technically feasible, I need more time for implementation. For a second one, I can quickly add support for |
Here's what i have been up to. Along with trying to have a bottom-line code that's working, i wanted to make sure the problem was coming from Go/Resty/Net-http. With my somewhat simple case, we are nevertheless at some edges of common use cases, so there was a chance the problem was coming from my server code. package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
func main() {
path := "my_file.mp4"
file, err := os.Open(path)
if err != nil { panic(err) }
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("colligere[profile]", filepath.Base(path))
var n int64
n = 1024
for n == 1024 {
n, _ = io.CopyN(part, file, 1024)
}
writer.Close()
req, err := http.NewRequest("POST", "http://myhost/my_endpoint", body)
if err != nil { panic(err) }
client := &http.Client{}
client.Do(req)
} Even CopyN doesn't do it (provided i used it properly). Memory consumption is three times the file size (so i would guess there other hidden buffers on the way), to a nice 7 GB RAM consumption in my case. So, despite my strong preference for am multipart solution, it's a lost cause, unless you implement a workaround of the Go net/http library. Doable, sure, but... So if you can come up with a handy, simple solution, with the file in the request body, i'll be happy to continue to use Resty; get this vital yet entirely technical and not functionnal phase of my workflow done. I'll perhaps have to adapt server code (much easier in comparison), and manually set the content length with one line of code and a file stat. Sounds a good deal to me, if you're willing to set yourself to the task. Thanks again, for your time and for witnessing and assisting my first, very hard, steps at Go. Cheers ! |
well, that's probably mime/multipart that would have to be patched/worked around, but you got my point... Cheers ! |
@lacravate Yeah, I got your point. Typically its best to use request body for large file upload. Multipart approach is overhead for large file upload. I will be implementing request body support (as I described in the second point), once done I will ping you then you can give it a try. |
@lacravate I have implemented it on branch large-file-support-on-body. This branch contains buffer less request body writing. I believe you're using prod version cd $GOPATH/src/gopkg.in/resty.v1
git pull && git checkout large-file-support-on-body Sample Code: package main
import (
"fmt"
"log"
"os"
"gopkg.in/resty.v1"
)
func main() {
f, err := os.Open("my_movie.mp4")
if err != nil {
log.Fatal(err)
}
defer f.Close()
// get the file info
fileInfo, err := f.Stat()
if err != nil {
log.Fatal(err)
}
resp, err := resty.R().
SetBody(f).
SetHeader("Content-Type", "video/mp4").
SetHeader("Content-Length", fmt.Sprintf("%v", fileInfo.Size())).
Post("http://myhost:4001/my_endpoint")
if err != nil {
log.Fatal(err)
}
fmt.Println("Response Code:", resp.StatusCode())
} Please give it try and let me know. |
Neat, thanks. I'm on another subject right now for the next few hiours. But i will sure test this today, and sure report it to you right after. Cheers ! |
sorry for the mess in my answers, but i have to leave now, i had the time to launch a very limited test and contrary to my first attempt it looks fine, no extra memory consumption. I'll get back at it in a few hours and let you know... Cheers ! |
i did not come right back at you because the results of my tests are mixed up, and i am not sure what to make out of them. I giive you what i have, and am ready to answer for precision if need be. Context :
Side notes :
Conclusion (possibly) :
HTH, |
@lacravate Thanks for getting back. One thing I can assure, the branch I gave you does zero buffer on sending request body. Let's get into facts:
What do you mean? Resty does the same behavior. As always I'm glad to improve |
i may come back with much more matter than now, but you're right : for the moment, facts. So in facts, is there a way to manually specify the content-length ? I tried to set the header, with no luck, i tried other stuff, to no avail. Is there a simple way, in my case, meaning a body specified otherwise than a buffer in bodyBuf, to explicitly set the content length ? Cheers ! |
@lacravate Yes you can set manually. I have updated the sample code for header |
i am pretty sure i tried that one. Here is the header and first line(s) of data gotten with a copy/paste of sample code :
If you have any other way, to get to that result... Thanks again, and anyway. Cheers ! |
don't bother with my last question, i found a way. If there's any question left, if ts in middleware.go code, where you write stuff to enforce Content-Length while i think net/http overrides this entirely. This part, according to my understanding (yet to be bettered), is void code. I'll come back later, if i get a finalized solution and tell you of it. Maybe that'll be of use to you. Cheers ! |
@lacravate Okay, Thank you. |
Closing it |
Hi,
i tried my luck with the other issues, sorry if this is a duplicate.
Is it possible to upload files without loading the entire content into memory ?
Cheers !
The text was updated successfully, but these errors were encountered: