使用Multipart内容类型将文件通过Ajax上传到GoLang服务器

huangapple go评论127阅读模式
英文:

Ajax Upload File to GoLang Server with Content Type Multipart

问题

我正在尝试使用多部分表单将音频文件上传到一个使用Golang服务器的服务器。然而,Go返回以下错误:

  1. multipart: NextPart: bufio: buffer full

我认为这表明我的Javascript请求中有一些不符合多部分格式的内容。这是我的Javascript代码:

  1. function UploadFile(file) {
  2. var xhr = new XMLHttpRequest();
  3. if (file.type == "audio/mpeg" && file.size <= $id("MAX_FILE_SIZE").value) {
  4. // start upload
  5. var boundary = '---------------------------' + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768);
  6. xhr.open("POST", $id("upload").action, true);
  7. xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
  8. xhr.setRequestHeader("X_FILENAME", file.name);
  9. xhr.send(file);
  10. }
  11. }

这是我的Golang服务器处理程序:

  1. func FileHandler(w http.ResponseWriter, r *http.Request) {
  2. var (
  3. status int
  4. err error
  5. )
  6. defer func() {
  7. if nil != err {
  8. http.Error(w, err.Error(), status)
  9. }
  10. }()
  11. // parse request with maximum memory of _24Kilobits
  12. const _24K = (1 << 20) * 24
  13. if err = r.ParseMultipartForm(_24K); nil != err {
  14. fmt.Println(err)
  15. status = http.StatusInternalServerError
  16. return
  17. }
  18. for _, fheaders := range r.MultipartForm.File {
  19. for _, hdr := range fheaders {
  20. // open uploaded
  21. var infile multipart.File
  22. if infile, err = hdr.Open(); nil != err {
  23. status = http.StatusInternalServerError
  24. return
  25. }
  26. // open destination
  27. var outfile *os.File
  28. if outfile, err = os.Create("./uploaded/" + hdr.Filename); nil != err {
  29. status = http.StatusInternalServerError
  30. return
  31. }
  32. // 32K buffer copy
  33. var written int64
  34. if written, err = io.Copy(outfile, infile); nil != err {
  35. status = http.StatusInternalServerError
  36. return
  37. }
  38. w.Write([]byte("uploaded file:" + hdr.Filename + ";length:" + strconv.Itoa(int(written))))
  39. }
  40. }
  41. }

如果有人知道我为什么会收到这个错误,我将非常感激。

英文:

I'm trying to upload an audio file to a Golang server using a multipart form. However, Go returns the error:

  1. multipart: NextPart: bufio: buffer full

I believe this indicates there is something not in the multipart format with my Javascript request. This is my Javascript:

  1. function UploadFile(file) {
  2. var xhr = new XMLHttpRequest();
  3. if (file.type == &quot;audio/mpeg&quot; &amp;&amp; file.size &lt;= $id(&quot;MAX_FILE_SIZE&quot;).value) {
  4. // start upload
  5. var boundary = &#39;---------------------------&#39; + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768);
  6. xhr.open(&quot;POST&quot;, $id(&quot;upload&quot;).action, true);
  7. xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;multipart/form-data; boundary=&quot; + boundary);
  8. xhr.setRequestHeader(&quot;X_FILENAME&quot;, file.name);
  9. xhr.send(file);
  10. }
  11. }

And this is my Golang server handler:

  1. func FileHandler(w http.ResponseWriter, r *http.Request) {
  2. var (
  3. status int
  4. err error
  5. )
  6. defer func() {
  7. if nil != err {
  8. http.Error(w, err.Error(), status)
  9. }
  10. }()
  11. // parse request with maximum memory of _24Kilobits
  12. const _24K = (1 &lt;&lt; 20) * 24
  13. if err = r.ParseMultipartForm(_24K); nil != err {
  14. fmt.Println(err)
  15. status = http.StatusInternalServerError
  16. return
  17. }
  18. for _, fheaders := range r.MultipartForm.File {
  19. for _, hdr := range fheaders {
  20. // open uploaded
  21. var infile multipart.File
  22. if infile, err = hdr.Open(); nil != err {
  23. status = http.StatusInternalServerError
  24. return
  25. }
  26. // open destination
  27. var outfile *os.File
  28. if outfile, err = os.Create(&quot;./uploaded/&quot; + hdr.Filename); nil != err {
  29. status = http.StatusInternalServerError
  30. return
  31. }
  32. // 32K buffer copy
  33. var written int64
  34. if written, err = io.Copy(outfile, infile); nil != err {
  35. status = http.StatusInternalServerError
  36. return
  37. }
  38. w.Write([]byte(&quot;uploaded file:&quot; + hdr.Filename + &quot;;length:&quot; + strconv.Itoa(int(written))))
  39. }
  40. }
  41. }

If anyone has any ideas why I'm getting this error, I'd greatly appreciate it.

答案1

得分: 3

经过长时间的与Ajax请求的艰苦战斗,我成功发送了正确的信息。以下是我使用的代码:

  1. var xhr = new XMLHttpRequest(),
  2. boundary=Math.random().toString().substr(2);
  3. var formdata = new FormData();
  4. formdata.append("file", file);
  5. xhr.open("POST", $id("upload").action, true);
  6. //xhr.setRequestHeader("content-type", "multipart/form-data; charset=utf-8; boundary=" + boundary);
  7. xhr.send(formdata);

请注意,头部信息不再使用,并且我发现你可以更轻松地将数据附加到formdata,而不是使用其他任何方法,例如这个链接中的方法:https://stackoverflow.com/questions/5933949/how-to-send-multipart-form-data-form-content-by-ajax-no-jquery#5935286

英文:

After a long, arduous battle with the Ajax request, I got it to send the right information. Here's the code I used:

  1. var xhr = new XMLHttpRequest(),
  2. boundary=Math.random().toString().substr(2);
  3. var formdata = new FormData();
  4. formdata.append(&quot;file&quot;, file);
  5. xhr.open(&quot;POST&quot;, $id(&quot;upload&quot;).action, true);
  6. //xhr.setRequestHeader(&quot;content-type&quot;, &quot;multipart/form-data; charset=utf-8; boundary=&quot; + boundary);
  7. xhr.send(formdata);

Note the header is no longer in use and I found you can attach data to formdata much easier than any other method such as this: https://stackoverflow.com/questions/5933949/how-to-send-multipart-form-data-form-content-by-ajax-no-jquery#5935286

答案2

得分: 0

不确定这个答案是否适合你,但是我能够使用客户端的form-data通过ajax上传文件,并在服务器端使用以下简短的Go代码片段:

  1. file, handler, err := r.FormFile("img") // img是form-data的键
  2. if err != nil {
  3. fmt.Println(err)
  4. return
  5. }
  6. defer file.Close()
  7. fmt.Println("文件正常")
  8. fmt.Println(handler.Filename)
  9. fmt.Println()
  10. fmt.Println(handler.Header)
  11. f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
  12. if err != nil {
  13. fmt.Println(err)
  14. return
  15. }
  16. defer f.Close()
  17. io.Copy(f, file)

这里的r*http.Request。附注:这只是将文件存储在相同的文件夹中,并不执行任何安全检查。

英文:

Not sure whether this answer suits you, but I was able to upload the file via ajax using form-data on a client side and the following small snippet of Go code on the server:

  1. file, handler, err := r.FormFile(&quot;img&quot;) // img is the key of the form-data
  2. if err != nil {
  3. fmt.Println(err)
  4. return
  5. }
  6. defer file.Close()
  7. fmt.Println(&quot;File is good&quot;)
  8. fmt.Println(handler.Filename)
  9. fmt.Println()
  10. fmt.Println(handler.Header)
  11. f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
  12. if err != nil {
  13. fmt.Println(err)
  14. return
  15. }
  16. defer f.Close()
  17. io.Copy(f, file)

Here r is *http.Request. P.S. this just stores the file in the same folder and does not perform any security checks.

huangapple
  • 本文由 发表于 2014年8月26日 04:17:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/25493706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定