get filename from google docs using laravel - php

My site has a feature where users can upload a link to their google docs file. What I want to do is list all the uploaded links in a place. While doing that I need to show the name of the file that is associated with the link.
I can extract the file id from the link and make sure the link is of google docs. Now I need to find a way to get the filename from that. I tried going through the google developer API for google drive, but it is for uploading/doing anything only on the authorized docs. My issue here is, my users upload the files manually to their docs which I have no control over. All I get is a sharable link and somehow get the name out of it. In addition, a thumbnail will also help.
I have tried doing this, but it throws error
$url = "https://www.googleapis.com/drive/v3/files/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA";
// and
$url = "https://docs.google.com/document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing"
$html= file_get_contents($url);
print_r($html);
A dummy link for anyone willing to help: https://docs.google.com/document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing

Since we are getting the URL to the file, we can do a couple of things -
get the id to the file
get what type of file is that
Before I explain how to do that, it is better to know that there can be 2 possible situations. One the file is a google docs file, the other google drive file. Those both start with different URLs.
$url = explode('/', Str::after(
Str::after($request->url, 'https://docs.google.com/'), 'https://drive.google.com/'
));
I am using 2 Str::after() to remove the unnecessary part from the URL. Then I am using explode to convert the URL into an array.
Since we have excluded the useless part from the URL, we are left with document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing in an array form.
So, if we try to do $url[2], we get the id of the file. Also, "document" is also a good thing to note about. I use those to show proper images. There can be 5 different types of them (4 for google docs and 1 for google drive). Those are - document, spreadsheets, forms, presentation for google docs, and file for google drive. I would recommend everyone store these in the database so that extra calculations are not necessary while displaying it.
Now, to answer the actual part of the question. How to get the name. I have created a new model method to handle that.
public function name()
{
$key = config('app.google_api_key');
$url = "https://www.googleapis.com/drive/v3/files/{$this->file_id}?key={$key}";
$response = Http::get($url)->json();
return $response['name'] ?? 'Private File';
}
Don't forget to add your Google API key in the config file app.php (You need to create one). You can get your API key from Google Developer Console and create a project-specific key. Just to note that this key need not be belonging to the user of the URL.
Also, a thing to note here is that $response returns error code if the file is not set to visible to the public or the file is deleted.

Related

How to delete cloudinary image via PHP

I have an cloudinary_id stored in DB and want to delete this image from Cloudinary.
According documentation I call desctroy method on uploadApi with id which returns result OK. But as I see the image is still available. Dont understand it.
Tis is the code:
$cloudinary = new Cloudinary($config);
return $cloudinary->uploadApi()->destroy($file_id);
This code returns Cloudinary\Api\ApiResponse #d6b5 result => "ok"
Can somebody tell me please what is wrong with this code?
Cloudinary uses CDN to ensure fast delivery of the media resources. That being said, when deleting a media via API, you may need to pass the optional parameter "invalidation" set to true in order to invalidate that object in their CDN.
Here are their API documentation below:
https://cloudinary.com/documentation/image_upload_api_reference#destroy_method
https://cloudinary.com/documentation/admin_api#delete_resources
You may use either upload API or admin API. Both achieve the same result.
Anthony

Youtube API V3 - How to get filename from fileDetails

I'm brand new to APIs so please excuse what is probably a long and stupid question. Can I modify this code I got from this sample script - https://developers.google.com/youtube/v3/code_samples/php#update_a_video_by_adding_new_tags - to return the original name of the uploaded file for one of my company's videos? Note: I have already modified the linked script to remove the updating of tags (i.e. I just had it print the video id and the current tags to test that I had the Oauth2 working and I did - so, I got that far at least.)
// Call the API's videos.list method to retrieve the video resource.
$listResponse = $youtube->videos->listVideos("snippet",
array('id' => $videoId));
I was thinking that changing to "snippet" to "fileDetails" is what I need. If so, then how do then extract just the original filename from $listResponse?
Welcome to the world of Google Development. Lets look at the documentation a little for videos.list.
If you check under response you will notice that it returns an array of video resources click on that and the documentation will take you to Videos resource representation as you can see there is lots of fun stuff here. Under snippet you find title.
snippet.title string The video's title. The property value has a
maximum length of 100 characters and may contain all valid UTF-8
characters except < and >. You must set a value for this property if
you call the videos.update method and are updating the snippet part of
a video resource.
On the main videos.list documentation page you will find some examples of how to use it with PHP. Here is a hunk of the first one I think you will like.
// Display the list of matching videos.
foreach ($videosResponse['items'] as $videoResult) {
$videos .= sprintf('<li>%s </li>',
$videoResult['snippet']['title']);
}
Googles documentation is very useful always check it.

Modify request path info

Now, let me guess what y'all may be thinking... "It's a bad idea to modify the path info before it's processed. Why would you ever want to do that? This is malicious behavior!!!"
I am trying to get a controller/action representation of my previous URL; gotten through Yii::app()->getRequest()->getUrlReferrer().
From Yii 2 issues, it's possible to set the path info for a new request and parse that request. However, from the Yii 1 source, the only methods which deals with the path info are getPathInfo() and decodePathInfo(). If there was a setPathInfo(), I could have used that and the urlManager->parseUrl() to achieve this. But we aren't allowed to set the path info.
How can I arrive at a controller/action representation of my previous URL?
Using PHP $_SERVER['HTTP_REFERER'] it's good way to find previous location but will give you incomplete url.
You can try this way in Yii 1.0 -
if your url like - www.domain.com?r=site/page
if(isset($_REQUEST['r']) && !empty($_REQUEST['r'])){
$previous_location = $_REQUEST['r'];
Yii::app()->user->setState('previous_location', $previous_location);
}
Another way-
$controller_name = Yii::app()->controller->id;
$action_name = Yii::app()->controller->action->id;
Yii::app()->user->setState('previous_location', $controller_name.'/'.$action_name);
so you can find out your previous location by -
echo Yii::app()->user->getState('previous_location');
It's may be help you to resolve your issue.
Yii does not allow the CHttpRequest object live past the parsing of the routes. And creating a new CHttpRequest is impossible after the app is created.
I realized the only way to go about this is the vanilla Yii::app()->controller->action object. From this, I could get the module, controller and action ID for the specific URL.

Using the Flickr API how can I get back the absolute path to an image?

Ok, this is not only how to get the URL to an image, it is a little more than that and I proceed to explain trying to be as clear as possible, I might point out that I am a totally newbie on this, I am a PHP Junior programmer and this is my first time using Flickr at all:
I have PHP website online, I have done all what is related to Key, Secret, Token and that. So basically I have a public image uploader that works fine. You could go into my website pick a picture and upload them to my Flickr account.
Now, they PHP for doing that is basically this one:
$apiKey = "(my API Key)";
$apiSecret = "(my API Secret)";
$permissions = "write";
$token = "(my Token)";
$f = new phpFlickr($apiKey, $apiSecret, true);
$f->setToken($token);
$f->sync_upload($path, $title);
return $f;
The phpFlickr object comes in the Flickr API, and $f in this case gives me back an array with the picture ID and some other data.
How can I get an absoulte path to the just uploaded picture in the form www.flickr.com/something/myPicture.jpg in order to build a HTML tag?
Probably what $f gives me is not enough. Any light over this would be great!
Hope it was clear.
Before I start writing, take a look at these links. They might have what you're looking for:
http://www.flickr.com/services/api/misc.urls.html
http://www.flickr.com/services/api/flickr.photos.getInfo.html
If you're trying to build an absolute path to a photo, you have to build the entire path based on the information that you get from a successful API call which is going to be located in $f. Looking at the first link I posted, there are a few ways to build an absolute path for a picture given that you have all of the information needed. The first method is to build the photo source URL, which comes in this format:
http://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}.jpg
or
http://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}_[mstzb].jpg
or
http://farm{farm-id}.staticflickr.com/{server-id}/{id}_{o-secret}_o.(jpg|gif|png)
The information required to build these links can be found in a successful call to the photos.getInfo API call that I posted above. Building the absolute path is as simple as just combining all of the variables together:
(I haven't touched PHP in a while, bear with me)
my $link = 'http://farm' . $farmid . '.staticflickr.com/' . $serverid . '/' . $id . '_' . $secret . '.jpg';
The second method is to build the webpage URL. This can either be grabbed directly from the photos.getinfo API call, or built manually given that you have the user-id and/or photo-id. If you have the required information, building the link is almost the same as the way I did it above. Check out the first link I posted for the actual URLs you need to build.
One last thing I should mention is that you should make sure that your API calls are working. I spent so much wasted time back when I was first learning how to use API's because I never checked the output of what the API calls were returning or my authentication was incorrect. Doing a vardump($f) (or something similar) and seeing what the calls are returning might help you visualize what needs to be done to get the information you need.
Ok, I just found how. In case anyone is interested:
$f = new phpFlickr($apiKey, $apiSecret, true);
$f->photos_getInfo(PHOTO_ID);
That gives you back an array with all what you need to complete the URL.

How do I display protected Amazon S3 images on my secure site using PHP?

I am trying to move images for my site from my host to Amazon S3 cloud hosting. These images are of client work sites and cannot be publicly available. I would like them to be displayed on my site preferably by using the PHP SDK available from Amazon.
So far I have been able to script for the conversion so that I look up records in my database, grab the file path, name it appropriately, and send it to Amazon.
//upload to s3
$s3->create_object($bucket, $folder.$file_name_new, array(
'fileUpload' => $file_temp,
'acl' => AmazonS3::ACL_PRIVATE, //access denied, grantee only own
//'acl' => AmazonS3::ACL_PUBLIC, //image displayed
//'acl' => AmazonS3::ACL_OPEN, //image displayed, grantee everyone has open permission
//'acl' => AmazonS3::ACL_AUTH_READ, //image not displayed, grantee auth users has open permissions
//'acl' => AmazonS3::ACL_OWNER_READ, //image not displayed, grantee only ryan
//'acl' => AmazonS3::ACL_OWNER_FULL_CONTROL, //image not displayed, grantee only ryan
'storage' => AmazonS3::STORAGE_REDUCED
)
);
Before I copy everything over, I have created a simple form to do test upload and display of the image. If I upload an image using ACL_PRIVATE, I can either grab the public url and I will not have access, or I can grab the public url with a temporary key and can display the image.
<?php
//display the image link
$temp_link = $s3->get_object_url($bucket, $folder.$file_name_new, '1 minute');
?>
<a href='<?php echo $temp_link; ?>'><?php echo $temp_link; ?></a><br />
<img src='<?php echo $temp_link; ?>' alt='finding image' /><br />
Using this method, how will my caching work? I'm guessing every time I refresh the page, or modify one of my records, I will be pulling that image again, increasing my get requests.
I have also considered using bucket policies to only allow image retrieval from certain referrers. Do I understand correctly that Amazon is supposed to only fetch requests from pages or domains I specify?
I referenced:
https://forums.aws.amazon.com/thread.jspa?messageID=188183&#188183 to set that up, but then am confused as to which security I need on my objects. It seemed like if I made them Private they still would not display, unless I used the temp link like mentioned previously. If I made them public, I could navigate to them directly, regardless of referrer.
Am I way off what I'm trying to do here? Is this not really supported by S3, or am I missing something simple? I have gone through the SDK documentation and lots of searching and feel like this should be a little more clearly documented so hopefully any input here can help others in this situation. I've read others who name the file with a unique ID, creating security through obscurity, but that won't cut it in my situation, and probably not best practice for anyone trying to be secure.
The best way to serve your images is to generate a url using the PHP SDK. That way the downloads go directly from S3 to your users.
You don't need to download via your servers as #mfonda suggested - you can set any caching headers you like on S3 objects - and if you did you would be losing some major benefits of using S3.
However, as you pointed out in your question, the url will always be changing (actually the querystring) so browsers won't cache the file. The easy work around is simply to always use the same expiry date so that the same querystring is always generated. Or better still 'cache' the url yourself (eg in the database) and reuse it every time.
You'll obviously have to set the expiry time somewhere far into the future, but you can regenerate these urls every so often if you prefer. eg in your database you would store the generated url and the expiry date(you could parse that from the url too). Then either you just use the existing url or, if the expiry date has passed, generate a new one. etc...
You can use bucket policies in your Amazon bucket to allow your application's domain to access the file. In fact, you can even add your local dev domain (ex: mylocaldomain.local) to the access list and you will be able to get your images. Amazon provides sample bucket policies here: http://docs.aws.amazon.com/AmazonS3/latest/dev/AccessPolicyLanguage_UseCases_s3_a.html. This was very helpful to help me serve my images.
The policy below solved the problem that brought me to this SO topic:
{
"Version":"2008-10-17",
"Id":"http referer policy example",
"Statement":[
{
"Sid":"Allow get requests originated from www.example.com and example.com",
"Effect":"Allow",
"Principal":"*",
"Action":"s3:GetObject",
"Resource":"arn:aws:s3:::examplebucket/*",
"Condition":{
"StringLike":{
"aws:Referer":[
"http://www.example.com/*",
"http://example.com/*"
]
}
}
}
]
}
When you talk about security and protecting data from unauthorized users, something is clear: you have to check every time you access that resource that you are entitled to.
That means, that generating an url that can be accessed by anyone (might be difficult to obtain, but still...). The only solution is an image proxy. You can do that with a php script.
There is a fine article from Amazon's blog that sugests using readfile, http://blogs.aws.amazon.com/php/post/Tx2C4WJBMSMW68A/Streaming-Amazon-S3-Objects-From-a-Web-Server
readfile('s3://my-bucket/my-images/php.gif');
You can download the contents from S3 (in a PHP script), then serve them using the correct headers.
As a rough example, say you had the following in image.php:
$s3 = new AmazonS3();
$response = $s3->get_object($bucket, $image_name);
if (!$response->isOK()) {
throw new Exception('Error downloading file from S3');
}
header("Content-Type: image/jpeg");
header("Content-Length: " . strlen($response->body));
die($response->body);
Then in your HTML code, you can do
<img src="image.php">

Categories