Google drive file upload and share it to public access - php

I am uploading files to google drive account, what i want to do is to make it readable, but not editable to the public. How can i do that?
$file = new Google_Service_Drive_DriveFile();
$file->title = $_POST['name'];
$file->shared = "public"; //i need to do this
$file->folder = "/somefolder/"; // and this
[optional]
It's actually 3 in 1 question: I also want to place that file into a specific folder on a drive, and i whant to know how to create that folder on google drive.

Might be useful for newbies:
<?php
$client = new Google_Client();
// SET Client ID, Client Secret, Tokens as per your mechanism
?>
Step 1:
Create the folder. The API will return the ID for the folder created.
Step 2:
Upload the file in to the folder with setParents([]);
Example:
<?php
// Upload the file to efgh folder which is inside abcd folder which is in the root folder
$file = new Google_Service_Drive_DriveFile();
$file->setParents(["abcd123", "efgh456"]); // abcd123 and efgh456 are IDs returned by API for the respective folders
$service = new Google_Service_Drive($client);
$service->files->create($file);
?>
$fileID = ""; // file ID returned by Drive.
Step 3:
Setting the permissions to shareable:
<?php
$permissionService = new Google_Service_Drive_Permission();
$permissionService->role = "reader";
$permissionService->type = "anyone"; // anyone with the link can view the file
$service->permissions->create($fileID, $permissionService);
?>
Reference: https://developers.google.com/drive/api/v3/reference/permissions/create

Related

Delete folder if no files exist within it - Google Drive API

I currently have the function:
function deleteFileUsingID($fileID) {
$this->service->files->delete($fileID);
}
How would I have to modify it such that after deleting the file, if no files exists within that folder, it deletes the folder itself.
I believe your goal as follows.
When there are no files in the specific folder, you want to delete the folder.
In this case, you can check whether the files are in the folder using the method of "Files: list" in Drive API.
Modified script:
Please set the folder ID to $folderId = '###';.
function deleteFileUsingID($fileID) {
$this->service->files->delete($fileID);
$folderId = '###'; // Please set the folder ID.
$fileList = $this->service->files->listFiles(array("q" => "'{$folderId}' in parents"));
if (count($fileList->getFiles()) == 0) {
$this->service->files->delete($folderId);
}
}
Or, when you want to retrieve the folder ID from $fileID, you can also use the following script.
function deleteFileUsingID($fileID) {
$folderIds = $this->service->files->get($fileID, array("fields" => "parents"))->getParents();
$this->service->files->delete($fileID);
if (count($folderIds) > 0) {
$folderId = $folderIds[0];
$fileList = $this->service->files->listFiles(array("q" => "'{$folderId}' in parents"));
if (count($fileList->getFiles()) == 0) {
$this->service->files->delete($folderId);
}
}
}
In this modified script, after $this->service->files->delete($fileID); was run, it checks whether the files are in the folder using the method of "Files: list". When no files in the folder, the folder is deleted.
Note:
In this case, the folder is deleted. So please be careful this. I would like to recommend to use the sample folder for testing the script.
Reference:
Files: list

Facebook Marketing API: Upload Image to library provided a URL

I am new to the Facebook Marketing API and what I am working on is to upload an image to my FB Marketing library.
Right now, I can successfully upload an image to the FB Marketing but unfortunately I cannot see if there is a way to upload an image from a URL.
Has anyone had any previous experience with that ?
Code sample:
Api::init(getenv('FACEBOOK_APP_ID'), getenv('FACEBOOK_APP_SECRET'), getenv('FACEBOOK_APP_TOKEN'));
/**
* {#inheritdoc}
*/
public function testFunc()
{
$adAccountId = getenv('FACEBOOK_APP_ACCOUNT_ID');
$account = new AdAccount();
$account->{AdAccountFields::ID} = $adAccountId;
$image = new AdImage(null, "act_{$account->id}");
$image->{AdImageFields::FILENAME} = getenv('FACEBOOK_APP_MARKETING_PATH').'fbTestImage.png';
$image->create();
$this->line('Image Hash: '.$image->{AdImageFields::HASH}.PHP_EOL);
}
You have to use PHP to pull the image from the URL write it to a temporary file, upload. that then delete the temporary file when complete (Not ideal but a solution). The the Node.js Marketing API you can supply the content rather than the filename to the API which is nice.
However a possible solution for now.
$url = "https://www.sample/image.png";
// Create output file name
$arr = explode("/",$url);
$img_file = dir(__FILE__).'/tmp_'.$arr[count($arr)-1];
// Load File contents from URL
$data = file_get_contents($url);
// Write Temporary File
$fp = fopen($img_file,"w");
fwrite($fp,$data);
fclose($fp);
// Then Push the temp file to Facebook
// Rest of FB Code...
$image->{AdImageFields::FILENAME} = $img_file;
// Wait for the Upload to complete then delete the temp file
unlink($img_file);

Dropbox account as Wordpress uploads folder

As I'm developing a site with the potential of holding a huge number of images I'm wondering if I can set the standard WordPress uploads folder to a Dropbox account?
And if so, how do I do that?
It would be great when I can implement it in a maner that even WordPress don't know it is a 'remote' folder. Media upload should work the same way as in a native WordPress setup.
I've read about the possibility to use another folder instead of wp-content/uploads but I could not find any info about using Dropbox for this.
Yes, you can do it. As long as you keep the same structure on Dropbox and save Dropbox shareable links as meta data for both the original file and generated sizes, a simple yet fully working setup for it would be something like the following, by using thephpleague/flysystem with their Dropbox Adapter:
Step 1
Add a file called composer.json to the root of your theme with this content:
{
"require": {
"league/flysystem": "^1",
"league/flysystem-dropbox": "^1"
}
}
Step 2
Install Composer by following these instructions
Step 3
Using the command line on your terminal/console, go to your theme directory and run:
composer install -o
Step 4
Create Dropbox App here.
I suggest that you select "App folder" as the type of access.
A directory matching the name of you app will be created on the "Apps" directory at the root of your Dropbox account; This will be your "uploads" directory on Dropbox.
Step 5
Go to your app admin page and generate a new access token.
Save the access token somewhere and also copy the "App secret"
Step 6
Add the following to your functions.php:
use League\Flysystem\AdapterInterface;
use League\Flysystem\Adapter\Local as LocalAdapter;
use League\Flysystem\Dropbox\DropboxAdapter;
use League\Flysystem\Filesystem;
use League\Flysystem\MountManager;
use Dropbox\Client as DropboxClient;
// Autoload vendors
require_once __DIR__ .'/vendor/autoload.php';
/**
* Class that will handle uploading to Dropbox
*
*/
class SO40950172Filesystem {
/**
* Contains several mounted filesystems
*
* #var League\Flysystem\MountManager object
*/
protected $filesystem;
/**
* Contains Dropbox client
*
* We need this accessible to create shareable links
*
* #var Dropbox\Client object
*/
protected $dropbox_client;
/**
* Instantiates this class
*/
public function __construct() {
// Get WordPress uploads directory info
$uploads_info = wp_upload_dir();
// Create Local filesystem
$local_adapter = new LocalAdapter($uploads_info['basedir']);
$local_fs = new Filesystem($local_adapter, [
'visibility' => AdapterInterface::VISIBILITY_PUBLIC
]);
// Create Dropbox filesystem
$this->dropbox_client = new DropboxClient($app_access_token, $app_secret);
$dropbox_adapter = new DropboxAdapter($this->dropbox_client, '/');
$dropbox_fs = new Filesystem($dropbox_adapter, [
'visibility' => AdapterInterface::VISIBILITY_PUBLIC
]);
// Set filesystem manager
$this->filesystem = new MountManager([
'local' => $local_fs,
'dropbox' => $dropbox_fs
]);
}
/**
* Uploads file to Dropbox
*
* #param string $path Path to file
* #return object Current object
*/
public function uploadToDropbox($path)
{
// Normalize path
$path = static::getNormalizedPath($path);
// Get content from the local file
$content = $this->read("local://$path");
// Push file to Dropbox
$this->put("dropbox://$path", $content);
return $this;
}
/**
* Deletes file from Dropbox
*
* #param string $path Path to file
* #return object Current object
*/
public function deleteFromDropbox($path)
{
// Normalize path
$path = static::getNormalizedPath($path);
// Delete file from Dropbox
$this->delete("dropbox://$path");
return $this;
}
/**
* Returns the unique identifier path section of a Dropbox URL
*
* #param string $path Path to file
* #return string Dropbox URL unique identifier
*/
public function getDropboxUrlID($path)
{
// Normalize path
$path = static::getNormalizedPath($path);
// Get unique link
$url = $this->dropbox_client->createShareableLink("/$path");
// Parse URL to retrive its path
$url_info = parse_url($url);
$url_path = $url_info['path'];
// Remove "s/" section and file name from the URL path
$id = str_replace(['s/', basename($path)], '', $url_path);
// Return Dropbox unique identifier for this file URL
return trim($id, '/');
}
/**
* Returns clean & relative paths
*
* #param string $path Raw path
* #return string Parsed path
*/
public static function getNormalizedPath($path)
{
// Get WordPress uploads directory info
$uploads_info = wp_upload_dir();
// Remove uploads base path so that we end up
// with the "/YYYY/MM/filename.extension" format
$path = str_replace($uploads_info['basedir'], '', $path);
// Remove uploads base url so that we end up
// with the "/YYYY/MM/filename.extension" format
$path = str_replace($uploads_info['baseurl'], '', $path);
// Remove forward slashes on both ends
$path = trim($path, '/');
// Return path
return $path;
}
/**
* Making sure all calls go to $this->filesystem
*
* #param string $name Method name
* #param array $args Method arguments
* #return mixed
*/
public function __call($name, array $args)
{
if (method_exists($this->filesystem, $name))
throw new \Exception("\League\Flysystem\MountManager doesn't have \"$name\" method");
return call_user_func_array([$this->filesystem, $name], $args);
}
}
// Manipulate media URLs sitewide
add_filter('wp_get_attachment_url', 'so_40950172_get_dropbox_url', 9, 2);
function so_40950172_get_dropbox_url($absolute_url, $post_id) {
// Get normalized path
$path = SO40950172Filesystem::getNormalizedPath($absolute_url);
// Get only the filename
$path = basename($path);
// Get Dropbox URL unique ID
$id = get_post_meta($post_id, 'dropbox_id_'. $path, true);
// Return absolute URL
return $id ? "https://dl.dropboxusercontent.com/s/$id/$path/?dl=0" : $path;
}
// Upload new and updated files to Dropbox
add_filter('wp_update_attachment_metadata', 'so_40950172_upload_to_dropbox', 9, 2);
function so_40950172_upload_to_dropbox($data, $post_id) {
// Get filesystem
$fs = new SO40950172Filesystem();
// Upload original file to Dropbox
$fs->uploadToDropbox($data['file']);
// Add Dropbox URL unique ID to meta data
add_post_meta($post_id, 'dropbox_id_'. basename($data['file']), $fs->getDropboxUrlID($data['file']));
// Upload intermediate image sizes
if (isset($data['sizes']) && $data['sizes']) {
// Get year and month prefix (e.g /YYYY/MM) from original file
$base_path = dirname($data['file']);
// Loop through all sizes
foreach ($data['sizes'] as $size_name => $size_data) {
// Set path for current size
$size_path = $base_path .'/'. $size_data['file'];
// Upload size to Dropbox
$fs->uploadToDropbox($size_path);
// Add Dropbox URL unique ID to meta data
add_post_meta($post_id, 'dropbox_id_'. basename($size_path), $fs->getDropboxUrlID($size_path));
}
}
return $data;
}
// Delete Dropbox file
add_filter('wp_delete_file', 'so_40950172_delete_dropbox_file');
function so_40950172_delete_dropbox_file($absolute_path) {
// Get filesystem
$fs = new SO40950172Filesystem();
// Delete file from Dropbox
$fs->deleteFromDropbox($absolute_path);
}
Step 7
On the code your just pasted into functions.php:
Replace $app_access_token with the Dropbox app access token you generated
Replace $app_secret with the Dropbox app secret
NOTES
The original file and generated sizes will also be saved locally, but you don't need to worry about them. You can even delete the local file after confirmation of a successful upload, if you want and/or care about disk space.
I also tested the built-in image editor and it worked without any issues.
If you ever need to move things on the Dropbox side and since there is no info saved on the database (this is just fine), all you need to do is to update the functions above.
Apparently you can mirror the WordPress structure on Dropbox, but you can't simply link to them using a base URL and the WordPress uploads structure to get the URLs, you really need to get the shareable link for each original file and generated sizes and store something about them as metadata. On the code above I chose to only store the unique part of the URL as metadata, which really is the only unique thing about them.
I know this is off-topic, but I would recommend either AWS S3 or Google Cloud Storage because you can access your files with the exact same file structure you have on Dropbox. No need to save anything as meta data.
that's an interesting idea, but WordPress uses DB relations in order to manage the uploaded images - so i think you must handle the images through the media uploader. TL:DR; - you can't.

How do i remove a file from Rackspace's Cloudfiles with their api?

I was wondering how do i remove a file from Rackspace's Cloudfiles using their API?
Im using php.
Devan
Use the delete_object method of CF_Container.
Here is my code in C#. Just guessing the api is similar for php.
UserCredentials userCredientials = new UserCredentials("xxxxxx", "99999999999999");
cloudConnection = new Connection(userCredientials);
cloudConnection.DeleteStorageItem(ContainerName, fileName);
Make sure you set the container and define any sudo folder you are using.
$my_container = $this->conn->get_container($cf_container);
//delete file
$my_container->delete_object($cf_folder.$file_name);
I thought I would post here since there isn't an answer marked as the correct one, although I would accept Matthew Flaschen answer as the correct one. This would be all the code you need to delete your file
<?php
require '/path/to/php-cloudfiles/cloudfiles.php';
$username = 'my_username';
$api_key = 'my_api_key';
$full_object_name = 'this/is/the/full/file/name/in/the/container.png';
$auth = new CF_Authentication($username, $api_key);
$auth->ssl_use_cabundle();
$auth->authenticate();
if ( $auth->authenticated() )
{
$this->connection = new CF_Connection($auth);
// Get the container we want to use
$container = $this->connection->get_container($name);
$object = $container->delete_object($full_object_name);
echo 'object deleted';
}
else
{
throw new AuthenticationException("Authentication failed") ;
}
Note that the "$full_object_name" includes the "path" to the file in the container and the file name with no initial '/'. This is because containers use a Pseudo-Hierarchical folders/directories and what end ups being the name of the file in the container is the path + filename. for more info see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Pseudo-Hierarchical_Folders_Directories-d1e1580.html
Use the method called DeleteObject from class CF_Container.
The method DeleteObject of CF_Container require only one string argument object_name.
This arguments should be the filename to be deleted.
See the example C# code bellow:
string username = "your-username";
string apiKey = "your-api-key";
CF_Client client = new CF_Client();
UserCredentials creds = new UserCredentials(username, apiKey);
Connection conn = new CF_Connection(creds, client);
conn.Authenticate();
var containerObj = new CF_Container(conn, client, container);
string file = "filename-to-delete";
containerObj.DeleteObject(file);
Note DonĀ“t use the DeleteObject from class *CF_Client*

How to do file uploads with PHP and the Zend Framework?

I am using Zend Framework 1.9.6. I think I've got it pretty much figured out except for the end. This is what I have so far:
Form:
<?php
class Default_Form_UploadFile extends Zend_Form
{
public function init()
{
$this->setAttrib('enctype', 'multipart/form-data');
$this->setMethod('post');
$description = new Zend_Form_Element_Text('description');
$description->setLabel('Description')
->setRequired(true)
->addValidator('NotEmpty');
$this->addElement($description);
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
->setRequired(true)
->addValidator('NotEmpty')
->addValidator('Count', false, 1);
$this->addElement($file);
$this->addElement('submit', 'submit', array(
'label' => 'Upload',
'ignore' => true
));
}
}
Controller:
public function uploadfileAction()
{
$form = new Default_Form_UploadFile();
$form->setAction($this->view->url());
$request = $this->getRequest();
if (!$request->isPost()) {
$this->view->form = $form;
return;
}
if (!$form->isValid($request->getPost())) {
$this->view->form = $form;
return;
}
try {
$form->file->receive();
//upload complete!
//...what now?
$location = $form->file->getFileName();
var_dump($form->file->getFileInfo());
} catch (Exception $exception) {
//error uploading file
$this->view->form = $form;
}
}
Now what do I do with the file? It has been uploaded to my /tmp directory by default. Obviously that's not where I want to keep it. I want users of my application to be able to download it. So, I'm thinking that means I need to move the uploaded file to the public directory of my application and store the file name in the database so I can display it as a url.
Or set this as the upload directory in the first place (though I was running into errors while trying to do that earlier).
Have you worked with uploaded files before? What is the next step I should take?
Solution:
I decided to put the uploaded files into data/uploads (which is a sym link to a directory outside of my application, in order to make it accessible to all versions of my application).
# /public/index.php
# Define path to uploads directory
defined('APPLICATION_UPLOADS_DIR')
|| define('APPLICATION_UPLOADS_DIR', realpath(dirname(__FILE__) . '/../data/uploads'));
# /application/forms/UploadFile.php
# Set the file destination on the element in the form
$file = new Zend_Form_Element_File('file');
$file->setDestination(APPLICATION_UPLOADS_DIR);
# /application/controllers/MyController.php
# After the form has been validated...
# Rename the file to something unique so it cannot be overwritten with a file of the same name
$originalFilename = pathinfo($form->file->getFileName());
$newFilename = 'file-' . uniqid() . '.' . $originalFilename['extension'];
$form->file->addFilter('Rename', $newFilename);
try {
$form->file->receive();
//upload complete!
# Save a display filename (the original) and the actual filename, so it can be retrieved later
$file = new Default_Model_File();
$file->setDisplayFilename($originalFilename['basename'])
->setActualFilename($newFilename)
->setMimeType($form->file->getMimeType())
->setDescription($form->description->getValue());
$file->save();
} catch (Exception $e) {
//error
}
By default, files are uploaded to the system temporary directory, which means you'll to either :
use move_uploaded_file to move the files somewhere else,
or configure the directory to which Zend Framework should move the files ; your form element should have a setDestination method that can be used for that.
For the second point, there is an example in the manual :
$element = new Zend_Form_Element_File('foo');
$element->setLabel('Upload an image:')
->setDestination('/var/www/upload')
->setValueDisabled(true);
(But read that page : there are other usefull informations)
If you were to move the file to a public directory, anyone would be able to send a link to that file to anyone else and you have no control over who has access to the file.
Instead, you could store the file in the DB as a longblob and then use the Zend Framework to provide users access the file through a controller/action. This would let you wrap your own authentication and user permission logic around access to the files.
You'll need to get the file from the /tmp directory in order to save it to the db:
// I think you get the file name and path like this:
$data = $form->getValues(); // this makes it so you don't have to call receive()
$fileName = $data->file->tmp_name; // includes path
$file = file_get_contents($fileName);
// now save it to the database. you can get the mime type and other
// data about the file from $data->file. Debug or dump $data to see
// what else is in there
Your action in the controller for viewing would have your authorization logic and then load the row from the db:
// is user allowed to continue?
if (!AuthenticationUtil::isAllowed()) {
$this->_redirect("/error");
}
// load from db
$fileRow = FileUtil::getFileFromDb($id); // don't know what your db implementation is
$this->view->fileName = $fileRow->name;
$this->view->fileNameSuffix = $fileRow->suffix;
$this->view->fileMimeType = $fileRow->mime_type;
$this->view->file = $fileRow->file;
Then in the view:
<?php
header("Content-Disposition: attachment; filename=".$this->fileName.".".$this->fileNameSuffix);
header('Content-type: ".$this->fileMimeType."');
echo $this->file;
?>
$this->setAction('/example/upload')->setEnctype('multipart/form-data');
$photo = new Zend_Form_Element_File('photo');
$photo->setLabel('Photo:')->setDestination(APPLICATION_PATH ."/../public/tmp/upload");
$this->addElement($photo);

Categories