$_FILES is empty when I send a file from WWWForm

Hi, I’m trying to send a file to a server using WWWForm, but I have a problem of _FILES receiving it, it doesn't receive any data, I checked that both (the _FILES[“name”] and filed name) are the same.

I’ve been reading that maybe is because the form is sent with application/x-www-form-urlenconded, but I tried to put in the headers the Content-Type as “multipart/form-data” and it results in a error “400 Bad Request”.

Also I tried to use UnityWebRequest and FormMultipartFileSection instead of WWW and WWWForm, but I’m getting a error code 400 with “Generic/Unknown HTTP error”

Any clues of what is happening? (I’ll post my cs and php codes below)

Regards

    IEnumerator UploadFileCo(string localFileName, string uploadURL)
    {
        WWW localFile = new WWW("file:///data/user/0/com.HeXentic.IldemaroApp/cache/PickedImage.jpg");
        Debug.Log("IMAGE PATH TRYING TO LOAD IS: " + localFile.url);
        yield return new WaitUntil(() => localFile.isDone);
        if (localFile.error == null)
            Debug.Log("Loaded file successfully");
        else
        {
            Debug.Log("Open file error: " + localFile.error);
            yield break; // stop the coroutine here
        }

        Texture2D tex = new Texture2D(163, 224, TextureFormat.RGBA32, false);
        WWW w = new WWW("file:///data/user/0/com.HeXentic.IldemaroApp/cache/PickedImage.jpg");

        yield return new WaitUntil(() => w.isDone);
        //tex = texture;
        if (w.bytesDownloaded > 0 && w.error == null)
        {
            w.LoadImageIntoTexture(tex);

            for (int i = 0; i <= profilesImages.Length - 1; i++)
            {
                profilesImages*.GetComponent<RawImage>().texture = tex;*

}

//byte[] imageBytes = tex.EncodeToJPG();

//FileStream fileSave;
//fileSave = new FileStream(Application.persistentDataPath + “/Save/picture.jpg”, FileMode.Create);

//BinaryWriter binary;
//binary = new BinaryWriter(fileSave);
//binary.Write(imageBytes);
//fileSave.Close();

/* for (int i = 0; i <= imageBytes.Length - 1; i++)
{
Debug.LogWarning("IMAGE BYTES INDEX: " + i + " VALUE = " + imageBytes.GetValue(i));
}*/

//WWWForm postForm = new WWWForm();
// version 1
//postForm.AddBinaryData(“theFile”,localFile.bytes);
// version 2
//postForm.AddBinaryData(“archivo-a-subir”, w.bytes , “demo.jpg” + “.jpg”, “image/jpeg”);
//Dictionary<string, string> headers = postForm.headers;
//headers.Add(“enctype”, “multipart/form-data”);
//postForm.AddField(“test”,“test”);
Debug.Log("Trying to upload the file: " + tex.GetRawTextureData());
Debug.Log("In the URL: " + uploadURL);
Debug.Log(“With the name of: " + UserAccountInfo.instance.email.Replace(”.", “_”) + “.png”);
//WWW upload = new WWW(uploadURL, postForm.data, headers);

//////////////////////////////////////////////
/// CON UNITY WEB REQUEST
//////////////////////////////////////////////

/*
List formData = new List();
formData.Add(new MultipartFormFileSection(“archivo-a-subir”,tex.EncodeToPNG(), UserAccountInfo.instance.email.Replace(“.”,“_”) + “.png”,“image/png”));

//WWWForm postForm = new WWWForm();
//postForm.AddBinaryData(“archivo-a-subir”, tex.EncodeToPNG(), UserAccountInfo.instance.email.Replace(“.”, “_”) + “.png”, “image/png”);
//Dictionary<string, string> headers = postForm.headers;
//headers[“Content-Type”] = “multipart/form-data”;
//byte[] formData = postForm.data;

UnityWebRequest upload = UnityWebRequest.Post(uploadURL, formData);
upload.SetRequestHeader(“Content-Type”, “multipart/form-data”);
upload.SetRequestHeader(“Content-Disposition”,“form-data”);
yield return upload.SendWebRequest();

*/
//////////////////////////////////////////////
/// CON WWW
//////////////////////////////////////////////

WWWForm postForm = new WWWForm();
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add(“Content-Type”, “multipart/form-data”);

foreach (KeyValuePair<string, string> kvp in headers)
{
//textBox3.Text += (“Key = {0}, Value = {1}”, kvp.Key, kvp.Value);
Debug.Log("Key = " + kvp.Key + ", Value = "+ kvp.Value + " ");
}

//headers[“Content-Disposition”] = “form-data”;
//postForm.AddBinaryData(“archivo-a-subir”, w.bytes , UserAccountInfo.instance.email.Replace(“.”, “_”) + “.jpg”, “image/jpeg”);
postForm.AddBinaryData(“archivo-a-subir”, tex.EncodeToPNG(), UserAccountInfo.instance.email.Replace(“.”, “_”) + “.png”, “file”);
//postForm.AddField(“test”,“test”);
WWW upload = new WWW(uploadURL, postForm.data, headers ); // test 1
//WWW upload = new WWW(uploadURL, postForm.data); // Test 2
yield return upload;

yield return new WaitUntil(() => upload.isDone);
if (upload.error == null)
{
Debug.Log(“upload done”);
//Debug.Log("ECHO OF RESPONSE: " + upload.downloadHandler.text);
Debug.Log("ECHO OF RESPONSE: " + upload.text);
}
else
{
//Debug.Log("Error during upload: " + upload.responseCode + ": " + upload.error);
Debug.Log("Error during upload: " + upload.error);
}
}
else
{
Debug.LogError(“ERROR EN OBTENER LA TEXTURA DE LA UBICACION EN EL TELEFONO”);
}
}
subir-archivos.php (in the server)
<?php
$target_path = “upload/”;
$target_path = target_path . basename( _FILES[‘archivo-a-subir’][‘name’]);
echo "
Target Path set as " . targetPath;* *echo " trying to move it";* *echo " getting name property" . _FILES[‘archivo-a-subir’][‘name’];

echo "
getting temp_name property" . _FILES['archivo-a-subir']['tmp_name'];* *if(move_uploaded_file(_FILES[‘archivo-a-subir’][‘tmp_name’], target_path))* *{* *echo " El archivo ". basename( _FILES[‘archivo-a-subir’][‘name’])." ha sido subido exitosamente!";

}
else
{
echo “Hubo un error al subir tu archivo! Por favor intenta de nuevo.”;
}

?>

Hi!

I have the same problem !

Did you make it work ?

Best regards !

You don’t seem to have the slightest idea how multipart content works since you completely ignore the headers that the WWWForm is providing and you create your own headers the wrong way.

For multipart posts the Content-Type header needs a boundary that is used to seperate the multiple parts from another. This is usually just a random string of characters. The WWWForm class does generate a boundary which is actually used in the data it composes. However this boundary needs to be announced in the header. The multipart format is roughly explained here.

However you don’t really have to care about that as the WWWForm does all this for you. Usually you don’t have to tinker with the headers so you can simply pass the WWWForm directly to the WWW constructor. However if you want to add additional headers you should first setup your WWWForm with all parts, after that get the headers from the WWWForm, add your own headers and then pass the custom headers dict to the WWW constructor.

Though do not overwrite the Content-Type header as it actually contains the boundary that the WWWForm uses.

edit

I just realised another quite important error which will make any server to reject the posted data. As mentioned below you passed “file” as mime type to AddBinaryData. This of course is not a valid mime type. Either remove the last parameter completele (Unity has an overload without the mimetype) or provide the correct mimetype yourself.

You have a lot of commented out code fragments where some are slightly more correct than the current code. Though my original answer still applies: Do not try to overwrite the Content-Type request header. Also note that the “Content-Disposition” header(s) can not be added to the headers dictionary as they apply to the actual multipart request body. Each section has it’s own headers which can’t be manipulated with the WWWForm. The assembly of the post body is done by the WWWForm class. The Content-Disposition is always “form-data” and the name is set to the provided name. Just have a look here

HI @HeXenticSpA

I finally managed to do it working :slight_smile:

So first, the png encoding ImageConversion.EncodeToPng never worked for me but ImageConversion.EncodeToJPG(tex) without setting the quality seems to work.

Secondly i changed the mime type.

Here is my request :

 List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        
        formData.Add(new MultipartFormDataSection("id", s.id.ToString()));
        formData.Add(new MultipartFormDataSection("x", s.x.ToString()));
        formData.Add(new MultipartFormDataSection("y", s.y.ToString()));
        formData.Add(new MultipartFormDataSection("id_vv", s.main_id.ToString()));
        formData.Add(new MultipartFormDataSection("eye", s.eye));
        **formData.Add(new MultipartFormFileSection("equi", *ImageConversion.EncodeToJPG(s.tex)*, "tile.jpg", "*image/jpeg*"));**
        UnityWebRequest www = UnityWebRequest.Post(Const.serverURL + "/api/vv/tile", formData);

Before the mimetype on the add of the jpg file was "“image/jpg”, i changed for “image/jpeg” and magically it worked :slight_smile:

I don’t know if it’s that or ImageConversion.EncodeToJPG(tex) (and no ImageConversion.EncodeToJPG(tex, quality).

So try to change the mime type to “image/jpeg” and the encoding to jpg :smiley: