Jump to content

Twitter API: JS and PHP


Mad_Griffith

Recommended Posts

Hi all,

I would like to understand how JS/jQuery can interact with PHP to upload a status and a picture from the HTML5 canvas to Twitter. I set up a similar thing for FB and it works.

 

I don't get how to do it for Twitter and I haven't found much about it. Could you explain to me how it works?

 

I currently have this JS/jQuery code as a starting point:

var formData = new FormData(),
    mimetype = canvas.toDataURL().substring(canvas.toDataURL().lastIndexOf(":") + 1, canvas.toDataURL().lastIndexOf(";")),
    blob = dataURItoBlob(canvas.toDataURL().split(',')[1], mimetype);

formData.append('source', blob);  

$('#twitter').click(

        function() {

                $.ajax({
                    url: '',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    cache: false,
                    success: function() {
                        $('#twitter').addClass('twitter-success');
                        setTimeout(
                            function() {
                                $('#twitter').removeClass('twitter-success');
                            }, 3000);
                    }
                });
            
        }

    );

Thank you!

Edited by Mad_Griffith
Link to comment
Share on other sites

I get this error when sending the data (it's a base64 canvas)... but data I am passing is there...

 

<br />
<b>Warning</b>:  file_get_contents(): Filename cannot be empty in <b>/web/htdocs/mywebsite.com/home/demos/projectname/twitter/twitteroauth/src/TwitterOAuth.php</b> on line <b>249</b><br />
Edited by Mad_Griffith
Link to comment
Share on other sites

I managed to have it working with the following:

			var canvasImg = canvas.toDataURL()

			$.ajax({
				url: './twitter/twitter.php',
				type: 'POST',
				data: {
					canvasImg: canvasImg
				},
				success: function(canvasImg) {
					console.log('success', canvasImg)
					$('#twitter').addClass('twitter-success');
					setTimeout(
						function() {
							$('#twitter').removeClass('twitter-success');
						}, 3000);
				}
			});

		}
<?php
    require "twitteroauth/autoload.php";
    use Abraham\TwitterOAuth\TwitterOAuth;
    $connection = new TwitterOAuth('x', 'x', 'x', 'x');
$msg = 'My custom text here';
$media = $connection->upload('media/upload', ['media' => $_POST['canvasImg']]);
$parameters = [
    'status' => $msg,
    'media_ids' => $media->media_id_string
];
$result = $connection->post('statuses/update', $parameters);
  ?>
Edited by Mad_Griffith
Link to comment
Share on other sites

I have a problem. The code above allows anybody to post the canvas image only to the twitter wall of the account that generated the keys. How can I allow people to post the canvas image on their own twitter wall?

 

So far this is what I have but it is not working.

 

In my app's main index file I have this AJAX request:

 

$('#twitter').click(function() {
var canvasImgData = canvas.toDataURL();
$.ajax({
url: './twitter/tweet-with-media.php',
type: 'POST',
data: {
canvasImgData: canvasImgData
},
crossDomain: true,
success: function() {
$('#twitter').addClass('twitter-success');
setTimeout(
function() {
$('#twitter').removeClass('twitter-success');
}, 3000);
}
});


});

The payload request:

canvasImgData:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAAOECAY...

Whereas the response is empty and these are the statuses:

 

9gzk15.png

 

I also created a TWEET-WITH-MEDIA.PHP file with this content:

<?php
session_start();
require 'twitteroauth/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;

define('CONSUMER_KEY', 'my consumer key'); // add your app consumer key between single quotes
define('CONSUMER_SECRET', 'my consumer secret'); // add your app consumer secret key between single quotes
define('OAUTH_CALLBACK', 'http://www.mywebsite.com/twitter/callback.php'); // your app callback URL

if (!isset($_SESSION['access_token'])) {
    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
    $request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));
    $_SESSION['oauth_token'] = $request_token['oauth_token'];
    $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
    $url = $connection->url('oauth/authorize', array('oauth_token' => $request_token['oauth_token']));
    header('Location:' . $url);
} else {
    $access_token = $_SESSION['access_token'];
    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['oauth_token'], $access_token['oauth_token_secret']);
    
    // getting basic user info
    $user = $connection->get("account/verify_credentials");
    
    // uploading media (image) and getting media_id
    $tweetWM = $connection->upload('media/upload', ['media' => $_POST['canvasImgData']]);
    // tweeting with uploaded media (image) using media_id
    $tweet = $connection->post('statuses/update', ['media_ids' => $tweetWM->media_id_string, 'status' => 'My status']);
}

Put this in CALLBACK.PHP (which is referenced also within the app I created in apps.twitter.com):

<?php
session_start();
require 'twitteroauth/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;
if (isset($_REQUEST['oauth_verifier'], $_REQUEST['oauth_token']) && $_REQUEST['oauth_token'] == $_SESSION['oauth_token']) {
    $request_token = [];
    $request_token['oauth_token'] = $_SESSION['oauth_token'];
    $request_token['oauth_token_secret'] = $_SESSION['oauth_token_secret'];
    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $request_token['oauth_token'], $request_token['oauth_token_secret']);
    $access_token = $connection->oauth("oauth/access_token", array("oauth_verifier" => $_REQUEST['oauth_verifier']));
    $_SESSION['access_token'] = $access_token;
    // redirect user back to index page
    header('Location: http://mywebsite.com/twitter/tweet-with-media.php');
}
Edited by Mad_Griffith
Link to comment
Share on other sites

Help with the above please to understand what's going on? If I browse straight away to the twitter.php file, it seems to work, as in it asks for the user agreement on adding the app. Is there anything wrong with the AJAX code?

Edited by Mad_Griffith
Link to comment
Share on other sites

the 400 is because one should be authenticated. but before authenticating, the redirect should work... at least that's my intention in the tweet-with-media.php file when I use:

header('Location: ' . $url);

Why is the header() function not working? What am I doing wrong?

Edited by Mad_Griffith
Link to comment
Share on other sites

It's working, that's why it's redirecting. That's why the server is responding with a 302 and including the location header telling it to go to the authorize URL. The authorize URL is returning the error response.

Link to comment
Share on other sites

I changed the JS like below, sending the base64 data via a form and opening the tweet-with-media.php file via window.open in the beforesend state.

 

When the tweet-with-media.php fopens up I get this

Warning: file_get_contents(): Filename cannot be empty in /path/to/TwitterOAuth.php on line 249

How can I debug this 400 bad request from Twitter? I am sorry, I am new to all this...

 

My JS:

$('#twitter').click(function() { 

var formData = new FormData();

var mimetype = canvas.toDataURL().substring(canvas.toDataURL().lastIndexOf(":") + 1, canvas.toDataURL().lastIndexOf(";")),
blobTW = dataURItoBlob(canvas.toDataURL().split(',')[1], mimetype);
formData.append('canvasToTwitter', blobTW);

$.ajax({
url: './twitter/tweet-with-media.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
cache: false,
beforeSend: function() {
window.open('tweet-with-media.php');
$('#twitter').addClass('twitter-beforesend');
},
success: function() {
$('#twitter').removeClass('twitter-beforesend');
$('#twitter').addClass('twitter-success');
setTimeout(
function() {
$('#twitter').removeClass('twitter-success');
}, 3000);
}
});


});
Edited by Mad_Griffith
Link to comment
Share on other sites

You keep showing that file_get_contents error but I don't see the code that is causing it. I don't know what the code around line 249 in TwitterOAuth.php is doing, or your code that calls it. I assume it's related to you sending image data instead of using a file on disk, but I can't suggest how to fix it without seeing the code throwing the error and your code which calls that function.

 

How can I debug this 400 bad request from Twitter? I am sorry, I am new to all this...

You need to check their documentation to see why that URL would return a 400 response. If you're saying that the user needs to be authenticated first, then when does that happen?
Link to comment
Share on other sites

This is the TwitterOAuth.php

Thank you !

<?php
/**
 * The most popular PHP library for use with the Twitter OAuth REST API.
 *
 * @license MIT
 */
namespace Abraham\TwitterOAuth;


use Abraham\TwitterOAuth\Util\JsonDecoder;


/**
 * TwitterOAuth class for interacting with the Twitter API.
 *
 * @author Abraham Williams <abraham@abrah.am>
 */
class TwitterOAuth extends Config
{
    const API_VERSION = '1.1';
    const API_HOST = 'https://api.twitter.com';
    const UPLOAD_HOST = 'https://upload.twitter.com';
    const UPLOAD_CHUNK = 40960; // 1024 * 40


    /** @var Response details about the result of the last request */
    private $response;
    /** @var string|null Application bearer token */
    private $bearer;
    /** @var Consumer Twitter application details */
    private $consumer;
    /** @var Token|null User access token details */
    private $token;
    /** @var HmacSha1 OAuth 1 signature type used by Twitter */
    private $signatureMethod;


    /**
     * Constructor
     *
     * @param string      $consumerKey      The Application Consumer Key
     * @param string      $consumerSecret   The Application Consumer Secret
     * @param string|null $oauthToken       The Client Token (optional)
     * @param string|null $oauthTokenSecret The Client Token Secret (optional)
     */
    public function __construct($consumerKey, $consumerSecret, $oauthToken = null, $oauthTokenSecret = null)
    {
        $this->resetLastResponse();
        $this->signatureMethod = new HmacSha1();
        $this->consumer = new Consumer($consumerKey, $consumerSecret);
        if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
            $this->token = new Token($oauthToken, $oauthTokenSecret);
        }
        if (empty($oauthToken) && !empty($oauthTokenSecret)) {
            $this->bearer = $oauthTokenSecret;
        }
    }


    /**
     * @param string $oauthToken
     * @param string $oauthTokenSecret
     */
    public function setOauthToken($oauthToken, $oauthTokenSecret)
    {
        $this->token = new Token($oauthToken, $oauthTokenSecret);
    }


    /**
     * @return string|null
     */
    public function getLastApiPath()
    {
        return $this->response->getApiPath();
    }


    /**
     * @return int
     */
    public function getLastHttpCode()
    {
        return $this->response->getHttpCode();
    }


    /**
     * @return array
     */
    public function getLastXHeaders()
    {
        return $this->response->getXHeaders();
    }


    /**
     * @return array|object|null
     */
    public function getLastBody()
    {
        return $this->response->getBody();
    }


    /**
     * Resets the last response cache.
     */
    public function resetLastResponse()
    {
        $this->response = new Response();
    }


    /**
     * Make URLs for user browser navigation.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return string
     */
    public function url($path, array $parameters)
    {
        $this->resetLastResponse();
        $this->response->setApiPath($path);
        $query = http_build_query($parameters);
        return sprintf('%s/%s?%s', self::API_HOST, $path, $query);
    }


    /**
     * Make /oauth/* requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array
     * @throws TwitterOAuthException
     */
    public function oauth($path, array $parameters = [])
    {
        $response = [];
        $this->resetLastResponse();
        $this->response->setApiPath($path);
        $url = sprintf('%s/%s', self::API_HOST, $path);
        $result = $this->oAuthRequest($url, 'POST', $parameters);


        if ($this->getLastHttpCode() != 200) {
            throw new TwitterOAuthException($result);
        }


        parse_str($result, $response);
        $this->response->setBody($response);


        return $response;
    }


    /**
     * Make /oauth2/* requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    public function oauth2($path, array $parameters = [])
    {
        $method = 'POST';
        $this->resetLastResponse();
        $this->response->setApiPath($path);
        $url = sprintf('%s/%s', self::API_HOST, $path);
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
        $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
        $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
        $this->response->setBody($response);
        return $response;
    }


    /**
     * Make GET requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    public function get($path, array $parameters = [])
    {
        return $this->http('GET', self::API_HOST, $path, $parameters);
    }


    /**
     * Make POST requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    public function post($path, array $parameters = [])
    {
        return $this->http('POST', self::API_HOST, $path, $parameters);
    }


    /**
     * Make DELETE requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    public function delete($path, array $parameters = [])
    {
        return $this->http('DELETE', self::API_HOST, $path, $parameters);
    }


    /**
     * Make PUT requests to the API.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    public function put($path, array $parameters = [])
    {
        return $this->http('PUT', self::API_HOST, $path, $parameters);
    }


    /**
     * Upload media to upload.twitter.com.
     *
     * @param string $path
     * @param array  $parameters
     * @param boolean  $chunked
     *
     * @return array|object
     */
    public function upload($path, array $parameters = [], $chunked = false)
    {
        if ($chunked) {
            return $this->uploadMediaChunked($path, $parameters);
        } else {
            return $this->uploadMediaNotChunked($path, $parameters);
        }
    }


    /**
     * Private method to upload media (not chunked) to upload.twitter.com.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    private function uploadMediaNotChunked($path, $parameters)
    {
        $file = file_get_contents($parameters['media']);
        $base = base64_encode($file);
        $parameters['media'] = $base;
        return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
    }


    /**
     * Private method to upload media (chunked) to upload.twitter.com.
     *
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    private function uploadMediaChunked($path, $parameters)
    {
        // Init
        $init = $this->http('POST', self::UPLOAD_HOST, $path, [
            'command' => 'INIT',
            'media_type' => $parameters['media_type'],
            'total_bytes' => filesize($parameters['media'])
        ]);
        // Append
        $segment_index = 0;
        $media = fopen($parameters['media'], 'rb');
        while (!feof($media))
        {
            $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
                'command' => 'APPEND',
                'media_id' => $init->media_id_string,
                'segment_index' => $segment_index++,
                'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK))
            ]);
        }
        fclose($media);
        // Finalize
        $finalize = $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
            'command' => 'FINALIZE',
            'media_id' => $init->media_id_string
        ]);
        return $finalize;
    }


    /**
     * @param string $method
     * @param string $host
     * @param string $path
     * @param array  $parameters
     *
     * @return array|object
     */
    private function http($method, $host, $path, array $parameters)
    {
        $this->resetLastResponse();
        $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path);
        $this->response->setApiPath($path);
        $result = $this->oAuthRequest($url, $method, $parameters);
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
        $this->response->setBody($response);
        return $response;
    }


    /**
     * Format and sign an OAuth / API request
     *
     * @param string $url
     * @param string $method
     * @param array  $parameters
     *
     * @return string
     * @throws TwitterOAuthException
     */
    private function oAuthRequest($url, $method, array $parameters)
    {
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
        if (array_key_exists('oauth_callback', $parameters)) {
            // Twitter doesn't like oauth_callback as a parameter.
            unset($parameters['oauth_callback']);
        }
        if ($this->bearer === null) {
            $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
            $authorization = $request->toHeader();
        } else {
            $authorization = 'Authorization: Bearer ' . $this->bearer;
        }
        return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
    }


    /**
     * Make an HTTP request
     *
     * @param string $url
     * @param string $method
     * @param string $authorization
     * @param array $postfields
     *
     * @return string
     * @throws TwitterOAuthException
     */
    private function request($url, $method, $authorization, $postfields)
    {
        /* Curl settings */
        $options = [
            // CURLOPT_VERBOSE => true,
            CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
            CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
            CURLOPT_HEADER => true,
            CURLOPT_HTTPHEADER => ['Accept: application/json', $authorization, 'Expect:'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_URL => $url,
            CURLOPT_USERAGENT => $this->userAgent,
        ];


        if($this->gzipEncoding) {
            $options[CURLOPT_ENCODING] = 'gzip';
        }


        if (!empty($this->proxy)) {
            $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
            $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
            $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
            $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
            $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
        }


        switch ($method) {
            case 'GET':
                break;
            case 'POST':
                $options[CURLOPT_POST] = true;
                $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
                break;
            case 'DELETE':
                $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
                break;
            case 'PUT':
                $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
                break;
        }


        if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields)) {
            $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
        }




        $curlHandle = curl_init();
        curl_setopt_array($curlHandle, $options);
        $response = curl_exec($curlHandle);


        // Throw exceptions on cURL errors.
        if (curl_errno($curlHandle) > 0) {
            throw new TwitterOAuthException(curl_error($curlHandle), curl_errno($curlHandle));
        }


        $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
        $parts = explode("\r\n\r\n", $response);
        $responseBody = array_pop($parts);
        $responseHeader = array_pop($parts);
        $this->response->setHeaders($this->parseHeaders($responseHeader));


        curl_close($curlHandle);


        return $responseBody;
    }


    /**
     * Get the header info to store.
     *
     * @param string $header
     *
     * @return array
     */
    private function parseHeaders($header)
    {
        $headers = [];
        foreach (explode("\r\n", $header) as $line) {
            if (strpos($line, ':') !== false) {
                list ($key, $value) = explode(': ', $line);
                $key = str_replace('-', '_', strtolower($key));
                $headers[$key] = trim($value);
            }
        }
        return $headers;
    }


    /**
     * Encode application authorization header with base64.
     *
     * @param Consumer $consumer
     *
     * @return string
     */
    private function encodeAppAuthorization($consumer)
    {
        // TODO: key and secret should be rfc 1738 encoded
        $key = $consumer->key;
        $secret = $consumer->secret;
        return base64_encode($key . ':' . $secret);
    }
}
Link to comment
Share on other sites

Line 249 is a comment, did you leave something out? Is it referring to the uploadMediaNotChunked method?

 

Both the uploadMediaNotChunked and uploadMediaChunked expect the "media" parameter to be a filename, but you are passing the canvas data in that parameter. Unless there is another method which takes that kind of data then you should save it as a file first and then pass the filename. You can delete the file after that.

Link to comment
Share on other sites

I believe it is referring to that method, yeah.

 

I did the change. Now the error is gone and I see this response:

Notice: Undefined index: canvasToTwitter in mypath/tweet-with-media.php on line 27

This is my new twitter-with-media.php.

<?php
header("Access-Control-Allow-Origin: *");
session_start();
require 'twitteroauth/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;


define('CONSUMER_KEY', 'x'); // add your app consumer key between single quotes
define('CONSUMER_SECRET', 'x'); // add your app consumer secret key between single quotes
define('OAUTH_CALLBACK', 'httwitter/callback.php'); // your app callback URL


if (!isset($_SESSION['access_token'])) {
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));
$_SESSION['oauth_token'] = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
$url = $connection->url('oauth/authorize', array('oauth_token' => $request_token['oauth_token']));
header('Location:' . $url);
} else {
$access_token = $_SESSION['access_token'];
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['oauth_token'], $access_token['oauth_token_secret']);


// getting basic user info
$user = $connection->get("account/verify_credentials");


$img = $_POST['canvasToTwitter'];
$data = base64_decode($img);
$path = getcwd();
$file = $path . "/temp-upload/twitter.png";
$success = file_put_contents($file, $data);


// uploading media (image) and getting media_id
$tweetWM = $connection->upload('media/upload', ['media' => $file]);
// tweeting with uploaded media (image) using media_id
$tweet = $connection->post('statuses/update', ['media_ids' => $tweetWM->media_id, 'status' => 'my status']);
}
unlink($file);
echo "<script>window.close();</script>";
Edited by Mad_Griffith
Link to comment
Share on other sites

Here I thought I appended 'canvasToTwitter' to the formData...

	$('#twitter').click(function() {
		
		canvasToData();
		
			$.ajax({
				url: 'tweet-with-media.php',
				type: 'POST',
				data: formData,
				processData: false,
				contentType: false,
				cache: false,
				beforeSend: function() {
					$('#twitter').addClass('twitter-beforesend');
				},
				success: function(data) {
					window.open('tweet-with-media.php');
				},
				complete: function() {
					$('#twitter').removeClass('twitter-beforesend');
					$('#twitter').addClass('twitter-success');
					setTimeout(
						function() {
							$('#twitter').removeClass('twitter-success');
						}, 3000);
				}
			});


		});

function canvasToData() {

	var canvasDataUrl = canvas.toDataURL("image/jpeg"),
	    canvasBlob = dataURItoBlob(canvasDataUrl);

	formData = new FormData();
	formData.append("canvasToTwitter", canvasBlob);

}

function dataURItoBlob(dataURI) {

var byteString = atob(dataURI.split(',')[1]),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0],
ab = new ArrayBuffer(byteString.length),
ia = new Uint8Array(ab);

for (var i = 0; i < byteString.length; i++) {

ia[i] = byteString.charCodeAt(i);

}

var bb = new Blob([ab], { "type": mimeString });

return bb;

}

And this is the payload request:

------WebKitFormBoundaryvABBdiIWg1ln71M1
Content-Disposition: form-data; name="canvasToTwitter"; filename="blob"
Content-Type: image/jpeg

------WebKitFormBoundaryvABBdiIWg1ln71M1--
Edited by Mad_Griffith
Link to comment
Share on other sites

Thank you. The response is empty, this is the request:

-----------------------------14391895511350467496552540129
Content-Disposition: form-data; name="canvasToData"; filename="blob"
Content-Type: image/jpeg


ÿØÿàJFIFÿÛC 


 

 


ÿÛC ÿÀ°ÿÄ 
ÿĵ}!1AQa"q2¡#B±ÁRÑð$3br 
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ 
ÿĵw!1AQaq"2B¡±Á #3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÚ?ùj¿?Ò 
( 

(

...
Edited by Mad_Griffith
Link to comment
Share on other sites

If the response is empty it probably means that PHP had an error. You should enable error reporting in your PHP.

 

If you put these commands at the top of the PHP file it will display error messages:

ini_set('display_errors', 1);
error_reporting(E_ALL);
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...