- Home /
How to Upload multiple files to a server using UnityWebRequest.Post();
I am trying to upload multiple files using UnityWebRequest.Post(), here's my code.
public void UploadFiles()
{
string[] path = new string[3];
path[0] = "D:/File1.txt";
path[1] = "D:/File2.txt";
path[2] = "D:/File3.txt";
UnityWebRequest[] files = new UnityWebRequest[3];
WWWForm form = new WWWForm();
for (int i = 0; i < files.Length; i++)
{
files[i] = UnityWebRequest.Get(path[i]);
form.AddBinaryData("files[]", files[i].downloadHandler.data, Path.GetFileName(path[i]));
}
UnityWebRequest req = UnityWebRequest.Post("http://localhost/File%20Upload/Uploader.php", form);
yield return req.SendWebRequest();
if (req.isHttpError || req.isNetworkError)
Debug.Log(req.error);
else
Debug.Log("Uploaded " + files.Length + " files Successfully");
}
The files are however created at the destination with size 0 bytes.
Here is my Uploader.php Code
<$php
$total = count($_FILES['files']['name']);
$uploadError = false;
for ( $i = 0; $i < $total; $i++)
{
$tmpFilePath = $_FILES['files']['tmp_name'][$i];
if ($tmpFilePath != "")
{
$newFilePath = "Uploads/".$_FILES['files']['name'][$i];
if (!move_uploaded_file($tmpFilePath, $newFilePath))
$uploadError = true;
}
}
if ($uploadError)
echo "Upload Error";
else
echo "Uploaded Successfully";
?>
I used this HTML Sample for reference. While in browser HTML code works perfectly. There is problem in Unity.
<form enctype="multipart/form-data" action="Uploader.php" method="POST">
Choose a file to Upload:
<input type="file" name="files[]" multiple="multiple" /><br>
<input type="submit" value="Upload File" />
</form>
This was solved by adding a yield statement after requesting the file in for loop. Add yield return files[i].SendWebRequest();
after files[i] = UnityWebRequest.Get(path[i]);
Answer by junedmmn · May 15, 2019 at 07:20 PM
In for
loop, in the C# code, after requesting the file, we must yield while the file is fetched. so using yield return files[i].SendWebRequest();
after requesting the file will solve the problem. Here is the modified code:
IEnumerator UploadMultipleFiles()
{
string[] path = new string[3];
path[0] = "D:/File1.txt";
path[1] = "D:/File2.txt";
path[2] = "D:/File3.txt";
UnityWebRequest[] files = new UnityWebRequest[path.Length];
WWWForm form = new WWWForm();
for (int i = 0; i < files.Length; i++)
{
files[i] = UnityWebRequest.Get(path[i]);
yield return files[i].SendWebRequest();
form.AddBinaryData("files[]", files[i].downloadHandler.data, Path.GetFileName(path[i]));
}
UnityWebRequest req = UnityWebRequest.Post("http://localhost/File%20Upload/Uploader.php", form);
yield return req.SendWebRequest();
if (req.isHttpError || req.isNetworkError)
Debug.Log(req.error);
else
Debug.Log("Uploaded " + files.Length + " files Successfully");
}
Rest of the code is fine. No changes in PHP code. HTML code is only for reference.
Answer by SuryaPrakashModi · May 21, 2020 at 04:57 AM
public IEnumerator UploadMultipleFiles(List texture2Ds, List spritesNames) {
texture2D = texture2Ds; WWWForm form = new WWWForm(); print("files length is " + texture2Ds.Count); print("files length is " + spritesNames.Count);
form.AddField("player_id", 5);
for (int i = 0; i < texture2Ds.Count; i++)
{
print("i = " + i);
byte[] imageData = texture2Ds[i].EncodeToPNG();
print("file size is " + imageData.Length);
string name = spritesNames[i];
print("name is " + name);
form.AddBinaryData("images", imageData, name, "image/png");
}
UnityWebRequest www = UnityWebRequest.Post(imageUploadAPI, form);
print("UploadMultipleFiles 2");
yield return www.SendWebRequest();
print("UploadMultipleFiles 3");
if (www.isHttpError || www.isNetworkError)
Debug.Log(www.error);
else
Debug.Log("Uploaded " + texture2Ds.Count + " files Successfully");
}
this worked for me
Answer by pixelgfx · Oct 20, 2021 at 07:34 PM
Neither of these seem to be answers! We still get zero byte file transfers despite adding the yield, and the image list sample is full of non-standard code! The PHP will never work if treated like a var... its a TAG so needs ?php
Update 1: Got it working - will post when it is tidied up. I think the problem is in how junedmmn was using the AddBinaryData method. The data argument was empty because the files are not being properly loaded before hand. I think that is what Surya was getting at but wasn't making clear.
We should load the file first with something like: WWW localFile = new WWW("file:///File1.txt");
Then after creating the form you can attach the file data properly using: form.AddBinaryData("file", localFile.bytes, "File1.txt");
Otherwise you are just instructing the PHP to create empty files with the same names and no byte data is transferred with the form!
UPDATE 2:
Tidied the C# and posted it below. Newbies should first test your server runs PHP. Save the following as test.php, upload it to your server, then open it in a browser. You should get a long list of properties if the server is running PHP.
<?php phpinfo() ; ?>
All being well then create the PHP handling file and post it onto your server in the same public folder as upload.php. Note this will put the upload files in a Log folder, so you MUST create the Log folder on your server first.
<?php
$thefile = $_FILES['file'];
if(!empty($thefile))
{
echo "Success!";
$tmpFilePath = $_FILES['file']['tmp_name']; // path to the temporary upload file
$newFilePath = "Log/".$_FILES['file']['name']; // path and file name where the temp file should be moved (in this case the Log/ folder)
if (!move_uploaded_file($tmpFilePath, $newFilePath)) // and move the file
$uploadError = true;
if ($uploadError)
echo "Move Error"; // couldn't move the temp file'
else
echo "Moved Successfully";
}
else
{
echo "Failed!"; // there was no file uploaded
}
?>
Now here is the adjusted C# script. Attach it to a game object and enter the url to your server/upload.php. Before you run the Unity scene and click the GUI button make sure you have created the three text files in the root of the Unity project. Make sure you add text in each file.
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System.IO;
public class Uploader : MonoBehaviour
{
public string url = null;
void StartUpload()
{
StartCoroutine("UploadMultipleFiles"); // run the upload request in the background
}
IEnumerator UploadMultipleFiles()
{
string[] path = new string[3]; // obviously there are better ways to set up your file list
path[0] = "File1.txt"; // ie Directory.Getfiles()
path[1] = "File2.txt";
path[2] = "File3.txt";
for (int i = 0; i < 3; i++) // upload each file one at a time
{
if (!File.Exists(path[i])) // check the upload file exists else quit with error
{
Debug.Log("ERROR! Can't locate the file to upload: " + path[i]);
yield break;
}
byte[] localFile = File.ReadAllBytes(path[i]); // IMPORTANT: if it does exist read all the file bytes into an array
yield return localFile; // wait until the local file has finished loading
WWWForm form = new WWWForm(); // get a web form ready - used to upload all data
form.AddBinaryData("file", localFile, path[i]); // copy/attach the local file data to the form and give the file a name
UnityWebRequest req = UnityWebRequest.Post(url, form); // url = http://yourserver.com/upload.php
yield return req.SendWebRequest(); // post the form and call the PHP to manage the server and wait until complete
if (req.isHttpError || req.isNetworkError) // trap and report any errors
Debug.Log(req.error);
else
Debug.Log("SUCCESS! File uploaded: " + path[i]); // else the file uploaded ok
}
}
void OnGUI()
{
if (GUILayout.Button("Click me!"))
{
StartUpload();
}
}
}
Now check the Log folder on your server and open each text file. You should see the bytes of the file content survived the transfer this time :)