Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Sending a Multipart Form Request to a Node server

Discussion in 'Multiplayer' started by solsnare, Oct 12, 2017.

  1. solsnare

    solsnare

    Joined:
    Dec 7, 2016
    Posts:
    16
    Hello!

    Not really sure if this is the right place to post this question, but here goes nothing.

    I've been working on an app that lets you create models within Unity, and i've got everything working except my interface with the web marketplace.

    I need to be able to send these files into my Node server in order to do a number of things but i am stuck on a step that i thought would be simple:

    I can't actually get the data to go through without the stream ending unexpectedly, or there being no data transferred on the other end (despite the Content-Length clearly growing and shrinking depending on what i add.)

    Here is my code from Unity:


    Code (CSharp):
    1. IEnumerator UploadFileToServer()
    2.     {
    3.         List<IMultipartFormSection> Data = new List<IMultipartFormSection>();
    4.         Data.Add(new MultipartFormDataSection("SomeField", "SomeData"));
    5.         Data.Add(new MultipartFormDataSection("SomeMoreFields", "SomeMOREData"));
    6.         Data.Add(new MultipartFormFileSection("F***inFile", UnityWebRequest.GenerateBoundary()));
    7.  
    8.         UnityWebRequest request = UnityWebRequest.Post(EndPoint, Data);
    9.  
    10.         yield return request.Send();
    11.  
    12.         if (request.isError)
    13.         {
    14.             Debug.Log("Error " + request.error);
    15.         }
    16.         else
    17.         {
    18.             Debug.Log("Form upload complete!");
    19.             foreach (KeyValuePair<string, string> stuff in request.GetResponseHeaders())
    20.             {
    21.                 Debug.Log("Got response header: key: " + stuff.Key + " val: " + stuff.Value);
    22.             }
    23.         }
    24.     }
    And once i send that through, i hit node:

    At first, i used "Multiparty" which kept getting "Stream ended unexpectedly"
    Heres the code for that:

    Code (JavaScript):
    1. exports.PostNewModelUnity = function (req, res) {
    2.  
    3.     console.log("Got new post from unity, parsing...");
    4.     var form = new multiparty.Form();
    5.  
    6.     //console.log(req.method);
    7.     console.log(util.inspect(req.headers));
    8.     console.log(util.inspect(req.body));
    9.  
    10.     form.parse(req, function (err, fields, files) {
    11.         if (err) {
    12.             console.log("Errored parsing req from unity: " + err);
    13.         } else {
    14.             console.log("Succesfully got post from Unity");
    15.             console.log(fields);
    16.             console.log(files);
    17.             util.inspect({
    18.                 fields: fields,
    19.                 files: files
    20.             });
    21.             res.end("Got some request");
    22.         }
    23.     });
    24. }
    Afterwards, i tried using "Multer" but i just don't seem to have any data within the body, or the files field after trying to parse it with the "Any()" command, i tried "Array(), Fields(), None(), etc.." to no avail.
    Code (JavaScript):
    1. exports.PostNewModelUnity = function (req, res,next) {
    2.  
    3.     console.log("Got new post from unity, parsing...");
    4.    
    5.     console.log(util.inspect(req.headers));
    6.     console.log("body");
    7.     console.log(util.inspect(req.body));
    8.     console.log("files");
    9.     console.log(util.inspect(req.files));
    10. }
    I've been trying different options, so many that i don't even know where to begin, and i kind of gave up for a month or two before getting back into it last night.

    There was this post
    http://answers.unity3d.com/questions/1354080/unitywebrequestpost-and-multipartform-data-not-for.html

    And i tried doing what this dude did, to no avail. It changed from "stream ended unexpectedly" to "Content-Type missing boundary"...

    Please give me a hand, my app is totally halted until i can get this working, and i am completely friggen lost.


    PS. If i posted in the wrong section, please let me know so i can repost.

    Thanks,
    - Sol.
     
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,292
    I'm no specialist, but have you tried uploading raw data via UnityWebRequest.Put? Maybe that will do the job.
     
    solsnare likes this.
  3. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    How big is the data you try to send?
     
  4. solsnare

    solsnare

    Joined:
    Dec 7, 2016
    Posts:
    16
    It's model files so it's variable. Depends on the size the user wanted to. But we're probably going to restrict model uploaded to around 30 megs max for now cause we have like no money to invest into this (however, we're uploading these onto sketchfab so we dont have to host it, so we'll see. the thing we need to upload is mostly to do with other users remixing each others content which i hope will be fairly light weight data).
     
  5. solsnare

    solsnare

    Joined:
    Dec 7, 2016
    Posts:
    16
    I just did this instead and with about a day of hitting my head against the wall i was able to do this.

    Dont think it's super efficient in the way im outputting the data from our stuff (it's not streamed, just one chunk) so it'll probably have to be looked at further down the line, but for now, and as a demo with a little amount of users im sure it'll be fine.

    Thank you!
     
  6. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    Have you tried using WWWForm?
     
  7. 3DGamesDeveloper

    3DGamesDeveloper

    Joined:
    Jan 16, 2016
    Posts:
    10
    I have a similar issue with unity using UnityWebRequest.Post.
    Code (CSharp):
    1. byte[] bytesArchivo = File.ReadAllBytes(fullPath);
    Code (CSharp):
    1.             List<IMultipartFormSection> camposFormulario = new List<IMultipartFormSection>();
    2.   camposFormulario.Add(new MultipartFormDataSection("field1", "value1"));
    3.             camposFormulario.Add(new MultipartFormDataSection("field2", "value2"));
    4.             camposFormulario.Add(new MultipartFormDataSection("field3", "value3"));
    5.             camposFormulario.Add(new MultipartFormDataSection("field4", "value4"));
    6.             camposFormulario.Add(new MultipartFormDataSection("field5", "value5"));
    7.             camposFormulario.Add(new MultipartFormDataSection("field6", "value6"));
    8.             string nom = Path.GetFileName(fullPath);
    9.             camposFormulario.Add(new MultipartFormFileSection("archivo", bytesArchivo, nom, "application/pdf"));
    10. Debug.Log(nom);
    11.             UnityWebRequest www = new UnityWebRequest();
    12.             www = UnityWebRequest.Post(url, camposFormulario);
    13. www.downloadHandler = new DownloadHandlerBuffer();
    14.  
    I tried using WWWForm.
    I get this Error: Generic/unknown HTTP error.
    Same post using postman It's working. Using WWWForm without the line
    Code (CSharp):
    1. camposFormulario.AddBinaryData("archivo", bytesArchivo, nom, "application/pdf");
    It's working. But I need Upload files with the form. Please, I need help with this issue. I spent a lot days working on this.
    I found this https://stackoverflow.com/questions...p-error-when-uploading-files-to-a-remote-form

    Anyway I am trying to resolve this using UnityWebRequest
     
    Last edited: Oct 4, 2018
  8. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    You need to read the file (File.ReadAllBytes()) and add it as as binary data.
     
  9. 3DGamesDeveloper

    3DGamesDeveloper

    Joined:
    Jan 16, 2016
    Posts:
    10
    My code has always been there, but I never wrote about it. My mistake. I added the snippet of code.
    Code (CSharp):
    1. byte[] bytesArchivo = File.ReadAllBytes(fullPath);
     
    Last edited: Oct 4, 2018
  10. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    Have you tried looking into the HTTP traffix using Fiddler or similar tool?
     
  11. 3DGamesDeveloper

    3DGamesDeveloper

    Joined:
    Jan 16, 2016
    Posts:
    10
    Yes, I did. Thanks for your reply.
    The attached file: TCP stream from Wireshark.
     
    Last edited: Oct 4, 2018
  12. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    Isn't this a server response at the end of the file you attached?

     
  13. 3DGamesDeveloper

    3DGamesDeveloper

    Joined:
    Jan 16, 2016
    Posts:
    10
    Yes, but in Unity I get this Error: Generic/unknown HTTP error.
    And that is not a normal flow. Using HTTP client from .NET is working, using postman It's working, using the code with wwwForm and without the field of binary data, It's working. That is not normal behavior. The request doesn't reach the PHP file in the server. I deleted all restrictions from .htaccess files. Maybe the server is blocking request from Unity because the server believes that something is wrong in this aspects:

    cross website scripting

    bad user agents

    SQL injection

    trojans

    session hijacking

    other exploits

    But I don't know why others request from unity are working. I have right configuration files permission 644 and 755 in Folders. Topics are taken from https://www.namecheap.com/support/k.../22/what-is-modsecurity-and-why-do-we-need-it
     
    Last edited: Oct 4, 2018
  14. 3DGamesDeveloper

    3DGamesDeveloper

    Joined:
    Jan 16, 2016
    Posts:
    10
    Solved. Thanks for your help. The issue was with ModSecurity. ModSecurity triggered one rule with a right request. If anyone else has the same issue contact to your hosting provider. Explain the problem. In my case, this link was useful https://www.namecheap.com/support/k.../22/what-is-modsecurity-and-why-do-we-need-it.

    PD: I don't know. why only that specific code triggered the rule in ModSecurity? In other requests were working right. The issue was only when binary data was added in that specific way.
     
    Last edited: Oct 5, 2018
  15. elhongo

    elhongo

    Joined:
    Aug 13, 2015
    Posts:
    42
    is there another approach for uploading a 200mb file or more? In mobile, reading all the bytes and having them in memory doesn't sound like the way to go, but I'm not finding any other alternatives
     
  16. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    There is UploadHandlerFile. You'd have to save entire upload content (body of HTTP message) to file first.