Get the link of the uploaded file with UnityWebRequest and php - c#

I want to allow the user to use a local image from his machine and upload it to the server.
What I did is use UnityWebRequest in-game, load the image, send it to a PHP file on the server, and wait for the reply to remember the URL where the file si saved(to save it in Playfab later).
This is the code I made so far:
private readonly string setAvatarUrl = "http://myurl.com/setavatar.php";
private readonly string playerIdField = "playfabid";
private readonly string imageField = "img_avatar";
public IEnumerator SaveImageToDB(Texture2D image)
{
byte[] bytes = image.EncodeToPNG();
WWWForm form = new WWWForm();
form.AddField(playerIdField, player.playerId);
form.AddBinaryData(imageField, bytes, "avatar.png", "image/png");
UnityWebRequest www = new UnityWebRequest();
www = UnityWebRequest.Post(setAvatarUrl, form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.LogError(www.error);
}
else
{
string jsonFromDB = www.downloadHandler.text; // Return empty string
string imageUrl = JsonUtility.FromJson<string>(jsonFromDB);
Debug.Log($"JSON returned: {jsonFromDB}");
if (!string.IsNullOrEmpty(imageUrl))
{
// Save the url
}
Debug.Log("Image upload complete!");
}
}
And this is the PHP file:
<?php
ini_set('display_errors',1);
$idplayfab = $_POST['playfabid'];
$path = 'avatar/'.$idplayfab;
if(file_exists($path)) {
//dir exist
$files = glob($path.'/*');
foreach($files as $file){
if(is_file($file))
unlink($file);
}
} else {
//not exist
mkdir($path);
}
$uploadfile = $path ."/". basename($_FILES['img_avatar']['name']);
if (move_uploaded_file($_FILES['img_avatar']['tmp_name'], $uploadfile)) {
$array = array('result' => 'ok', 'url' => 'http://myurl.com/'.$uploadfile);
$json = json_encode($array);
return $json;
} else {
$array = array('result' => 'ko');
$json = json_encode($array);
return $json;
}
?>
The image is saved on the server but the problem is when I try to get the JSON to get the URL, the string is empty and I don't understand why.
I tried tons of solutions like this one or this one but I cannot figure it out.
I also tried to use the deprecated WWW instead, but still, it doesn't work.
I'm kinda new to PHP so maybe it could be the PHP part the problem I believe.

Not an PHP expert but:
Afaik return is only used to evaluate certain functions e.g. for success or in order to further handle the result of something before responding to the client on server side.
What you want to do is rather sending your content as the http result to the client
=> You should rather use echo or print which is used to generate the http output.

Related

Flutter VideoPlayerController network request from web api

I am making a flutter app and using the VideoPlayerController library package and requesting video content via network:
VideoPlayerController newController = VideoPlayerController.network(
"http://192.168.1.1:9999/S3/get-object/name-of-video.mp4");
My Web API Backend is .NET Core 3 and the controller endpoint is this:
[AllowAnonymous]
[HttpGet("get-object/{url}")]
public async Task<FileStreamResult> GetObject(string url)
{
// Seperate out only the filename
string[] res = url.Split(new string[] { "%2F" }, StringSplitOptions.None);
string fileName = res.LastOrDefault();
Stream imageStream = await S3Helper.ReadObjectData(_appSettings, fileName);
Response.Headers.Add("Content-Disposition", new ContentDisposition
{
FileName = fileName,
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
}.ToString());
if (fileName.Contains(".jpg") || fileName.Contains(".jpeg"))
{
return File(imageStream, "image/jpeg");
}
else if (fileName.Contains(".png"))
{
return File(imageStream, "image/png");
}
else if (fileName.Contains(".mp4"))
{
return File(imageStream, new MediaTypeHeaderValue("video/mp4").MediaType, true);
}
else
{
return null;
}
}
However, when I create a widget that uses a Network image, it actually works. I'm not sure what the difference is.
CachedNetworkImage(
imageUrl: "http://192.168.1.1:9999/S3/get-object/name-of-image.jpg",
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
fit: BoxFit.contain,
),
The .Net Core Backend has the video coming via an http get request as an inline video, similar to this one:
https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4
The error I get from my flutter app shows up like this:
Source error. E/ExoPlayerImplInternal(24687): com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to http://192.168.1.1:9999/S3/get-object/name-of-video.mp4
I don't know about ios. But android doesn't allow http://. You need to provide a link starting https://.
To allow the http:// or others
add this line on androids AndroidManifest.xml.
Location android\app\src\main\AndroidManifest.xml
android:usesCleartextTraffic="true"
This should look like this:

Exception when downloading Asset Bundle on Android

I'm getting the following exception when I build my game for android
WWW download had an error: java.lang.IllegalArgumentException: uri ==
null
Now I haven o idea why this is happening because it works fine in the editor. Here is the relevant code :
assetLoader.BundleURL = "ftp://user:pass#81.161.248.122/Unity-Uri/AssetBundles/seasonalcontent/christmas";
assetLoader.version = 1;
assetLoader.StartDownload();
and the actual download code :
IEnumerator DownloadAndCache()
{
// Wait for the Caching system to be ready
while (!Caching.ready)
yield return null;
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, version))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
SeasonManager.assets = bundle.LoadAllAssets();
Debug.Log("Stop");
OnContentLoaded();
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
Edit: I got this from the documentation : ftp:// protocol support is limited to anonymous downloads only. Is ftp not supported on android ?
Edit 2: As suggest in the comments I tried this and it results in a Login failed error :
IEnumerator makeRequest()
{
string authorization = authenticate("username", "pass");
string url = "ftp://ipgoeshere";
UnityWebRequest www = UnityWebRequest.Get(url);
www.SetRequestHeader("AUTHORIZATION", authorization);
yield return www.Send();
if (www.isError)
{
Debug.Log(www.error);
}
else
{
AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;
SeasonManager.assets = bundle.LoadAllAssets();
}
}
string authenticate(string username, string password)
{
string auth = username + ":" + password;
auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
auth = "Basic " + auth;
return auth;
}
To clarify I've made sure that the username password and the server address are correct. I have simply removed them from the code here for obvious reasons.

Unity C#, WWWForm post to Python Flask Server

Hi I am making a game in unity and I need to post information to my python flask server I think that the best method is to use the WWWForms in Unity C# but I can't seem to make it post. Here is my C# Unity Code:
IEnumerator Upload() {
WWWForm form = new WWWForm();
form.AddField("Username", "Stan");
form.AddField("Password", "123456");
using(UnityWebRequest www = UnityWebRequest.Post("http://myserver.com/newuser/", form)) {
yield return www.Send();
if(www.isError) {
Debug.Log(www.error);
}
else {
Debug.Log("Form upload complete!");
}
}
}
It alsways says "From upload complete" and I don't get any errors but when I check my SQL Database it hasn't received the information.
I am pretty sure that my server side code is right because I can post successfully to it through the Form but here is the code anyway:
Python Flask:
class Users(db.Model):
__tablename__ = "userstable"
userid = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(4096))
password = db.Column(db.String(4096))
#app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
#app.route("/newuser", methods=["GET", "POST"])
def NewUser():
if request.method == "GET":
return render_template("NewUser.html")
new_user = Users(username=request.form["Username"], password=request.form["Password"])
db.session.add(new_user)
db.session.commit()
return redirect(url_for('NewUser'))
Please Help, and if possible it would be nice to know how to do get requests as well, Thanks!
Stan.

How do I access a database in Unity?

I am trying to POST data to my database in Unity and it doesn't seem to be working. I know it is probably a very stupid mistake as I do have little knowledge in this field.
The C# script I have:
void logIn(string test) {
WWWForm form = new WWWForm();
form.AddField("action","send");
form.AddField("var1",test);
string url = "http://www.prizechief.com/unitycon.php";
WWW w = new WWW(url, form);
}
void Start() {
string sample = "Works";
logIn(sample);
}
My PHP code
<?php
$con = #mysqli_connect("server","un","pass", "db") or die("Could not connect " . mysqli_connect_error() . "Please try again later.");
$var1 = $_GET['var1'];
echo $var1;
mysqli_Query($con,"INSERT INTO test (var) VALUE ('$var1')");
?>
Also, a hint on how to use GET to receive information would be greatly appreciated!
Try this. That should do the WWW request and set $_GET['var1'] = to value1 in your PHP script. Now of course you will have to change that to your variable down the road. But just to test for now. If this doesn't work let me know what the debug logs print out.
void Start () {
string url = "http://www.prizechief.com/unitycon.php?var1=value1";
WWW www = new WWW(url);
StartCoroutine(WaitForRequest(www));
}
IEnumerator WaitForRequest(WWW www)
{
yield return www;
// check for errors
if (www.error == null)
{
Debug.Log("WWW Ok!: " + www.data);
} else {
Debug.Log("WWW Error: "+ www.error);
}
}
EDIT
Remember to go into Edit > Player Settings > Editor and change the URL to your domain.

I can post text to Twitter in Unity3D but I need to be able to post a photo

So I got this free plugin from the Unity asset store called Let's Tweet in Unity and it works perfectly for posting text but I cannot figure out how to use https://upload.twitter.com/1/statuses/update_with_media.xml
instead of http://api.twitter.com/1/statuses/update.xml?status={0} which is what it is using now. It is written in C# which I don't really know and I am not experienced in the twitter api either. In general I'm new to coding. I'm learning JS.
This plugin has done what I assume is the hardest part which is talking to twitter with the consumer key, secret, etc. The part that I am guessing needs to be changed is below but I could also send you the whole file.
private static readonly string PostTweetURL = "http://api.twitter.com/1/statuses/update.xml?status={0}";
public static IEnumerator PostTweet(string text, string consumerKey, string consumerSecret, AccessTokenResponse response, PostTweetCallback callback)
{
if (string.IsNullOrEmpty(text) || text.Length > 140)
{
Debug.Log(string.Format("PostTweet - text[{0}] is empty or too long.", text));
callback(false);
}
else
{
string url = string.Format(PostTweetURL, UrlEncode(text));
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("status", text);
// Need to fill body since Unity doesn't like an empty request body.
byte[] dummmy = new byte[1];
dummmy[0] = 0;
// HTTP header
Hashtable headers = new Hashtable();
headers["Authorization"] = GetHeaderWithAccessToken("POST", url, consumerKey, consumerSecret, response, parameters);
WWW web = new WWW(url, dummmy, headers);
yield return web;
if (!string.IsNullOrEmpty(web.error))
{
Debug.Log(string.Format("PostTweet - failed. {0}", web.error));
callback(false);
}
else
{
string error = Regex.Match(web.text, #"<error>([^&]+)</error>").Groups[1].Value;
if (!string.IsNullOrEmpty(error))
{
Debug.Log(string.Format("PostTweet - failed. {0}", error));
callback(false);
}
else
{
callback(true);
}
}
}
}
Try this: UniShare, it supports post photo to twitter. Besides, it also supports sharing to lots of other social platforms like Facebook, linked in, etc. And support iOS, Android, Mac.

Categories

Resources