I'm trying to upload an image to facebook using graph api. I want to submit the image as a file instead of providing a URL which is another option. I'm using PHP Laravel and guzzle to achieve this. Unfortunately when I upload the file I'm getting an error which would seem to indicate that the image is not recognised.
This is the documentation I am using
https://developers.facebook.com/docs/graph-api/reference/page/photos/#publish
This is my error message
message: "Client error: `POST https://graph.facebook.com/v12.0/99999999999/photos` resulted in a `400 Bad Request` response:\n{\"error\":{\"message\":\"(#324) Requires upload file\",\"type\":\"OAuthException\",\"code\":324,\"fbtrace_id\":\"ACxilINTWYdb3wGOXfGg7 (truncated...)\n"
Here is my code
public function media(Request $request)
{
$facebookPageConnection = FacebookPageConnection::find(2);
$file = $request->file('file');
$client = new Client();
$body = $client->post("https://graph.facebook.com/v12.0/$facebookPageConnection->facebook_page_id/photos", [
'multipart' => [
[
'name' => 'message',
'contents' => 'test post'
],
[
'name' => 'source',
'contents' => base64_encode(file_get_contents($file))
],
[
'name' => 'access_token',
'contents' => $facebookPageConnection->access_token
]
]
])->getBody();
return json_decode($body);
}
My mistake was to use
file_get_contents
and
base64_encode
Instead to get it to work I needed to use fopen
$body = $client->post("https://graph.facebook.com/v12.0/$facebookPageConnection->facebook_page_id/photos", [
'multipart' => [
[
'name' => 'message',
'contents' => 'test post'
],
[
'name' => 'source',
'contents' => fopen($file, 'rb')
],
[
'name' => 'access_token',
'contents' => $facebookPageConnection->access_token
]
]
])->getBody();
Related
I'm trying to figure out how to implement the following REST PUT using Guzzle. I've tried using multipart and json, but I'm not sure what the syntax should be for having the parameters with a streamed xml file.
Can anyone help me translate this into a proper query? Below is what I tried so far, but it returns an error because it says the ProjectXML must be included.
$newUri = sprintf('%s/projects/%s/storage', $api_base, $testPid);
$newResp = $client->put($newUri,
[
'headers' => [
'Authorization' => sprintf("HubApi %s", $api_key),
],
'multipart' => [
[
'name' => 'ProjectXml',
'contents' => file_get_contents("xml/$testPid.xml")
],
[
'name' => 'ProjectId',
'contents' => $testPid
],
[
'name' => 'HubUserId',
'contents' => "xxxxxxx-xxxxx-xxxx-xxxxx-xxxxxxxx"
],
[
'name' => 'ProductId',
'contents' => "$(package:ourcompany/ourproducttype)/products/ProductABC123"
],
[
'name' => 'ThemeUrl',
'contents' => "$(package:ourcompany/ourproducttype)/themes/themename-white-Classic"
],
]
]
);
Response:
`400 Bad Request - Validation Error` response:
{"code":"RequestValidationError","message":"'Project Xml' should not be empty."}
I'm trying to create a multipart form for upload file in my API.
According the docs of guzzle :
\\$data = picture of form
\\$uri = Endpoint in my API
$this->client->post($uri, [
'multipart' => [
[
'name' => 'picture',
'contents' => file_get_contents($data),
]
],
'headers' => $headers
]);
When I'm using Insomnia or Postman :
I'm not understand why it not working in Guzzle.
$file = new File($data->getPathname());
$tmp_picture_path = Storage::putFile("temp_dir", $file);
$tmp_picture = Storage::readStream($tmp_picture_path);
$response = $this->client->post(
$uri,
[
'multipart' => [
[
'name' => 'picture',
'contents' => $tmp_picture,
'filename' => "avatar." . $data->getClientOriginalExtension()
]
],
'headers' => $headers
]
);
Storage::delete($tmp_picture_path);
Just save locally the file and read the stream dor send it properly.
I have a form where video can be uploaded and sent to remote destination. I have a cURL request which I want to 'translate' to PHP using Guzzle.
So far I have this:
public function upload(Request $request)
{
$file = $request->file('file');
$fileName = $file->getClientOriginalName();
$realPath = $file->getRealPath();
$client = new Client();
$response = $client->request('POST', 'http://mydomain.de:8080/spots', [
'multipart' => [
[
'name' => 'spotid',
'country' => 'DE',
'contents' => file_get_contents($realPath),
],
[
'type' => 'video/mp4',
],
],
]);
dd($response);
}
This is cURL which I use and want to translate to PHP:
curl -X POST -F 'body={"name":"Test","country":"Deutschland"};type=application/json' -F 'file=#C:\Users\PROD\Downloads\617103.mp4;type= video/mp4 ' http://mydomain.de:8080/spots
So when I upload the video, I want to replace this hardcoded
C:\Users\PROD\Downloads\617103.mp4.
When I run this, I get an error:
Client error: POST http://mydomain.de:8080/spots resulted in a 400 Bad Request response: request body invalid: expecting form value 'body`'
Client error: POST http://mydomain.de/spots resulted in a 400 Bad Request response:
request body invalid: expecting form value 'body'
I'd review the Guzzle's multipart request options. I see two issues:
The JSON data needs to be stringified and passed with the same name you're using in the curl request (it's confusingly named body).
The type in the curl request maps to the header Content-Type. From $ man curl:
You can also tell curl what Content-Type to use by using 'type='.
Try something like:
$response = $client->request('POST', 'http://mydomain.de:8080/spots', [
'multipart' => [
[
'name' => 'body',
'contents' => json_encode(['name' => 'Test', 'country' => 'Deutschland']),
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file',
'contents' => fopen('617103.mp4', 'r'),
'headers' => ['Content-Type' => 'video/mp4']
],
],
]);
While using the multipart option, make sure you are not passing content-type => application/json :)
If you want to POST form fields AND upload file together, just use this multipart option. It's an array of arrays where name is form field name and it's value is the POSTed form value. An example:
'multipart' => [
[
'name' => 'attachments[]', // could also be `file` array
'contents' => $attachment->getContent(),
'filename' => 'dummy.png',
],
[
'name' => 'username',
'contents' => $username
]
]
The following code seems to work, but the Slack API saves the file a plain text.
protected function upload($file)
{
$client = $this->guzzle;
if (!$token) {
$token = env('SLACK_TOKEN');
}
$response = $client->request('POST', env('SLACK_API') . "/files.upload?token=$token", [
'form_params' => [
'name' => $file->getFilename(),
'content' => File::get($file->getRealPath()),
'filename' => $file->getFilename(),
'filetype' => 'image',
'channels' => "#_test",
]
]);
return json_decode((string)$response->getBody());
}
When I use the guzzle multipart post, I get the error: 'no_file_data' I feel like I am missing something.
Is there a way to upload images or non-text files using the files.upload method in the Slack API?
Almost as soon as I posted this question, I realized that I was formatting the array incorrectly on the multipart post in guzzle.
This seems to work:
$response = $this->guzzle->post(env('SLACK_API') . "/files.upload?token=$token",
['multipart' =>
[
[
'name' => 'filename',
'contents' => $file->getClientOriginalName()
],
[
'name' => 'file',
'contents' => fopen($file,'r')
],
[
'name' => 'channels',
'contents' => '#_test'
]
]
]);
I'm new to using sendgrid web api v3. link here
Right now. It was easy to send a plain html using there api 'POST https://api.sendgrid.com/v3/mail/send' but I have this instance where we will attach a file (csv/xls,pdf) and I can't seem to get it right.
Here is my code below:
My function postSendMail
public function postSendMail($data = [])
{
if ( ! arrayHasValue($data) ) $this->error(__METHOD__, "Data is empty.");
$request = Curl::to( $this->apiUrl.'mail/send' )
->withHeader('Authorization: Bearer '. $this->apiKey)
->withData( $data )
->asJson(true)
->enableDebug(storage_path('logs/laravel-'.php_sapi_name().'.log'))
->post();
return $request;
}
//my instance
$sendgrid = new Sendgrid;
$data = [
'personalizations' => [
[
'to' => [
[ 'email' => 'myemail#gmail.com' ]
],
'subject' => 'Hello, World!'
]
],
'from' => [
'email' => 'myemail#gmail.com',
'name' => 'my_site'
],
'content' => [
[
'type' => 'text',
'value' => 'Hello, World!'
]
],
'track_settings' => [
[
'click_tracking' => true,
'open_tracking' => true
]
],
'attachments' => [
[
'content' => base64_encode(config('global.UPLOAD_PATH') . '/my_file.pdf'),
'type' => 'application/pdf',
'filename' => 'my_file.pdf',
'disposition' => 'attachment'
]
]
];
$lists = $sendgrid->postSendMail($data);
Mail was successfully sent but when I view the attached file, it was corrupted/unable to view. Can anyone help me? :(
Please help.
The problem is that you are not reading the file into an object and then encoding that object; you're encoding a string containing the file path.
'content' => base64_encode(config('global.UPLOAD_PATH') . '/my_file.pdf')
All of your attachments in the tests are probably the same size, and smaller than the actual file as a result.
Try something like:
$imagedata = file_get_contents(config('global.UPLOAD_PATH') . '/my_file.pdf');
$base64 = base64_encode($imagedata);
Coming to main point you need to get file content either by curl request or by file_get_content then encode the that content into attachments->content parameter, Please check following code which works for me:
'attachments' => [
[
'content' => base64_encode(file_get_contents(config('global.UPLOAD_PATH') . '/my_file.pdf')),
'type' => 'application/pdf',
'filename' => 'my_file.pdf',
'disposition' => 'attachment'
]
]