У меня есть приложение php 5.6, и мне наконец-то удалось собрать сценарий загрузки в Твиттере, в комплекте с oauth и всем остальным ...
За исключением того, что я делаю Я могу только инициировать частичную загрузку, но не добавлять к ней APPEND, поскольку команда APPEND возвращает статус 408 (в соответствии с им это МОЖЕТ означать CANCELLED_REQUEST, хотя в теории это тайм-аут.) И никакого вывода примерно через 5 минут
Кто-нибудь знает, почему это происходит, или имеет какую-то подсказку?
Код ниже:
<?php
// Twitter limits: 4 images. 1 video, 1 gif.
/////////////////////////////////////////////////////////////////////////////////
$consumer_key = 'XXXXXXXXXXXXXX';
$consumer_secret = 'XXXXXXXXXXXXXXXXx';
$token_secret = 'XXXXXXXXXXXXXX';
$token = 'XXXXXXXXXXXX';
/////////////////////////////////////////////////////////////////////////////////
$settings = [
"consumer_key" => $consumer_key,
"consumer_secret" => $consumer_secret,
"token" => $token,
"token_secret" => $token_secret
];
function makeOAuth($settings, $method, $request_url, $postfields) {
$signature_key = rawurlencode($settings['consumer_secret']) . '&' . rawurlencode($settings['token_secret']);
$oauth = array(
'oauth_consumer_key' => $settings['consumer_key'],
// 'oauth_callback' => "http%3A%2F%2Fmyapp.com%3A3005%2Ftwitter%2Fprocess_callback",
'oauth_nonce' => hash('md5', time()),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_token' => $settings['token'],
'oauth_timestamp' => time(),
'oauth_version' => '1.0'
);
if (!is_null($postfields)) {
foreach ($postfields as $key => $value) {
$oauth[$key] = $value;
}
}
$return = array();
ksort($oauth);
foreach($oauth as $key => $value)
{
$return[] = rawurlencode($key) . '=' . rawurlencode($value);
}
$to_be_signed= $method . "&" . rawurlencode($request_url) . '&' . rawurlencode(implode('&', $return));
$signature = base64_encode(hash_hmac('sha1', $to_be_signed, $signature_key, true));
$oauth['oauth_signature'] = $signature;
$auth = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key => $value)
{
if (in_array($key, array('oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
'oauth_signature_method', 'oauth_timestamp', 'oauth_token', 'oauth_version'))) {
$values[] = "$key=\"" . rawurlencode($value) . "\"";
}
}
$auth .= implode(', ', $values);
return $auth;
}
$upload_url = 'https://upload.twitter.com/1.1/media/upload.json';
$fname = 'new_account_btn.png';
echo 'opening '. realpath('../fotos/grande/' . $fname).'...';
$file = fopen(realpath('../fotos/grande/' . $fname), 'rb');
$size = fstat($file)['size'];
$mime_type = mime_content_type(realpath('../fotos/grande/' . $fname));
$postfields = array(
"command" => "INIT",
'media_type' => $mime_type,
// 'media_category' => 'tweet_video',
'total_bytes' => $size
);
var_dump($postfields);
// INITIALIZE upload
echo "requesting $upload_url..";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $upload_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
curl_setopt($ch, CURLOPT_HEADER,false);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields, '', '&'));
$oauth = makeOAuth($settings,'POST', $upload_url, $postfields);
echo $oauth;
curl_setopt($ch, CURLOPT_HTTPHEADER, [ $oauth, 'Expect: ']);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
var_dump($result);
$mediaId = $result['media_id_string'];
var_dump($mediaId);
$segmentId = 0;
while (!feof($file)) {
$chunk = fread($file, 25000);
echo strlen($chunk);
$postfields = array(
"command" => "APPEND",
"media_id" => $mediaId,
"segment_index" => $segmentId,
"media" => $chunk
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $upload_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');#####
curl_setopt($ch, CURLOPT_TIMEOUT, 60*10); # Modified: time out in 10 minutes.
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 60*10); ###
$request = '';
$border = '--------------------' . uniqid();
foreach ($postfields as $key => $value) {
$request .='--' . $border . "\r\n";
$request.= 'Content-Disposition: form-data; name=' . $key;
if ($key == "media") {
$request.= "\r\nContent-Type: application/octet-stream";
}
/* if ($key == "media") {
// $request.= '; filename="media"';
}
*/
// See codebird's _getMultipartRequestFromParams and _checkForFiles
$request .= "\r\n\r\n" . $value . "\r\n";
}
$request.= '--' . $border . "--\r\n";
var_dump($request);
#curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields, '', '&'));
#$oauth = makeOAuth($settings,'POST', $upload_url, $postfields);
$oauth = makeOAuth($settings,'POST', $upload_url, []);
echo $oauth;
#curl_setopt($ch, CURLOPT_HTTPHEADER, [ $oauth, 'Expect: ']);
echo 'Content-Length: '. strlen($request);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Length: '. strlen($request),
'Content-Type: multipart/form-data; boundary=' . $border,
$oauth,
'Expect: '
]);
$appendResult= curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo('chunk: '. $segmentId);
echo ('status:'. $status);
echo "append result:";
var_dump($appendResult);
echo curl_error($ch);
echo 'curl_errno:'.curl_errno($ch);
echo "-------------------------------------------------------";
curl_close($ch);
die();
$segmentId++;
}
Также да, файл существует!
Редактировать: я изменил свой запрос APPEND на использование media_data (полезная нагрузка base64 вместо двоичного, как описано здесь ), но безрезультатно. Я получаю точно такой же результат.