medvedo medvedo - 5 months ago 8
PHP Question

Trying to upload an image (that gets sent as a byte[]) to my domainfolder/server in PHP

With this current code when I send a byte [] (and the imagename) from my frontend I receive this echo in the log "upload failed".
I have an existing folder on my domain named "photosFolder" where I try to store my image and its imagename that I send from the frontend.

I am a bit confused now how to make this work so I added an move_uploaded_file that I frequently saw when I googled this issue. Is that the correct approach?

This is the PHP-code that I currently have.

<?php

$input = file_get_contents('php://input');
$value = json_decode($input, true);
if (!empty($value)) {

file_put_contents($value['photo_name'], base64_decode($value['photo_data']));

$image_name = $value['photo_name'];
$image_data = $value['photo_data'];

if(move_uploaded_file($image_data, "photosFolder/$image_name")) {

echo "image uploaded!";
}

else {
echo "upload failed";
}
}

?>


I send my byte [] like this from my frontend:

static public async Task<bool> createPhotoThree(string imgName, byte[] imgData) {
var httpClientRequest = new HttpClient();

var postData = new Dictionary<string, object>();

postData.Add("photo_name", imgName);
postData.Add("photo_data", imgData);

var jsonRequest = JsonConvert.SerializeObject(postData);

HttpContent content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json");

var result = await httpClientRequest.PostAsync("http://myadress.com/test.php", content);
var resultString = await result.Content.ReadAsStringAsync();
return true;
}

Answer

Suppose I'm sending a transparent gif 1x1 size. In the real life size of this gif will be 47 bytes. For this reason I'll call your C# method like this:

await createPhotoThree("transparent.gif", imgData);

where imgData is a byte[47], containing that 47 bytes of transparent gif.

In this case, at the php side I will recieve from php://input the following:

{"photo_data":"R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOwAAAAA=","photo_name":"transparent.gif"}

So, all I need to do is just $value = json_decode($input, true); to make an array from that input. And, put somewhere recieved file. At your case, you need to change your php code like this:

$input = file_get_contents('php://input');
$value = json_decode($input, true);
if (!empty($value)) {
    $image_name = $value['photo_name'];
    $image_data = base64_decode($value['photo_data']);
    if(file_put_contents("photosFolder/$image_name", $image_data)) {
        echo "image uploaded!";
    } else {
        echo "upload failed";
    }
} else {
    echo "json error";
}

move_uploaded_file() will work only with regular file uploads, but to make a regular file upload, just like the browser it does, you'll need to setup HTTP header

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryz0vLt59InlueCCBI

and properly form a POST-body, somthing like this:

------WebKitFormBoundaryz0vLt59InlueCCBI
Content-Disposition: form-data; name="uploaded_file"; filename="transparent.gif"
Content-Type: image/gif

<image content goes here>
------WebKitFormBoundaryz0vLt59InlueCCBI--

and work with it from $_FILES array and in that case move_uploaded_file() will work as desired.

I think, working with json a little bit easier than with regular file upload. Of curse, here we some sequrity issues, like checking from who we are recieving uploaded file, but that's another topic =)