Checking if a blob exists in Azure Blob storage (php) - php

Simple question; how do you check if a blob exists using PHP in Azure blob storage using the file name? I can't seem to find it in the API.
Cheers

I was looking for this today and this was the top search result so wanted to give my solution here which uses the prefix option to find only blobs which match the name I'm looking for.
You will need to include use MicrosoftAzure\Storage\Blob\Models\ListBlobsOptions; as well.
function blobExists($name)
{
global $blobClient, $blobContainer;
$listBlobsOptions = new ListBlobsOptions();
$listBlobsOptions->setPrefix($name);
$result = $blobClient->listBlobs($blobContainer, $listBlobsOptions);
return count($result->getBlobs());
}

Use the PHP SDK for Azure.
/ Create blob REST proxy.
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString);
// Get blob.
$blob = $blobRestProxy->getBlob("mycontainer", "myblob");
if ($blob) {
//blob exists
}

Solution for those using PHP SDK v4.10
http://phpazure.codeplex.com/
$storageClient = $this->azure->get_blob_storage();
//check if blob exists
$exists = $storageClient->blobExists(<container name>, <blob name>);
Go into the blob.php inside the SDK folder to see a complete list of API functions.

Related

Laravel 6 Storage results in a 404 error when trying to fetch files

I have tried to setup an upload script in Laravel and have followed the instructions in the docs.
I created a Symlink using the Laravel script and it looks like the following
storage -> /Users/username/Sites/switch/storage/app/public
The problem arrives when I go to upload the image and then get result of the image url in return. As you can see to match the symlink I set the folder to be public below.
$path = $request->file('manufacturer_image_name')->store('public');
echo asset($path);
and this returns
http://127.0.0.1:8000/public/XxIX7L75cLZ7cf2xzejc3E6STrcjfeeu3AQcSKz1.png
the problem is this doesn't work and throws a 404 but if I manually change the url from "public" to "storage" it will find the image.
http://127.0.0.1:8000/storage/XxIX7L75cLZ7cf2xzejc3E6STrcjfeeu3AQcSKz1.png
Shouldn't
echo asset($path);
be returning a url containing storage instead of public?
assett($path) is for generating a URL for assets that are just in the public folder, things like the Mix generated CSS and JS files. If you user Laravel Storage to save the file, you also have to use Laravel storage to generate the file URL.
Storage::url('file.jpg');
Well, there are a lot of ways to do that, pick anyone which fits you best.
// using storage_path helper
storage_path('public/' . $filename);
// you could make a double-check with File::exist() method
$path = storage_path('public/' . $filename);
if (!File::exists($path)) {
abort(404);
}
// using asset helper
asset('storage/your_folder/image.png');
// using url helper
url('storage/your_folder/image.png');
// using Storage facade
Storage::url($photoLink)
Here is the simplest and exact thing for your issue
if(!empty($request->file('manufacturer_image_name'))){
$path = storage_path('public/image/');
$image_path = Storage::disk('public')->put('manufacturer_image_name', $request->file('manufacturer_image_name'));
//Assuming you have a model called Manufacturer and created $manufacturer = new Manufacturer()
$manufacturer->manufacturer_image_name = isset($image_path) ? "storage/".$image_path : "";
}
Thanks for the help, I discovered this answer the fits nearly perfectly what I am after. Laravel: Storage not putting file inside public folder
This was what I ended up with.
if($request->file('manufacturer_image_name')){
$path = Storage::disk('public')->put('logo', $request->file('manufacturer_image_name'));
echo $path;
}
$path now returns "logo/filename.ext" instead of "public/ or storage/" so I can store this directly in the db.

Laravel Storaget get file contents

I want to know if you do the following in my code below how do you check if the file exists e.g
{
$file = Storage::disks('local')->get($file);
// then test if $file exists
}
You can check the existence of the file with the code below for your local storage,
$file_exists = Storage::disk('local')->exists($file);
You can read more about storage on Laravel Document at Laravel Filesystem.
Note: in the document you will check disk('s3'). It depends on what connection we are using defined in config/filesystem.php(the configuration file for the filesystem in laravel).
OR simply you can use check the condition by
if(Storage::disk('local')->exists($file)) {
}
It will also work for you.
There's a clear example in the docs, if you take a look.
$exists = Storage::disk('s3')->exists('file.jpg');

Use file_get_contents to to download multiple files at same time in php?

UDDATE: THIS IS AN S3 BUCKET QUESTION (SEE ANSWER)
I am looking to upload some code that reads files from an S3 bucket which uses the file_get_contents command to download a file one at a time.
Start
file_get_contents(s3://file1.json)
Wait until finished , then start next download:
file_get_contents(s3://file2.json)
And I want instead for them to all start at once to save time. like this:
Start both at same time:
file_get_contents(s3://file1.json)
file_get_contents(s3://file2.json)
Wait for them both at same time to finish.
I have seen multi curl requests but nothing for file_get_contents on this topic, is it possible ?
EDIT: Currently the code I am looking at uses s3:// which doesn't seem to work with curl. This is a way of getting to Amazon's S3 bucket.
EDIT2: Sample of current code :
function get_json_file( $filename = false ){
if(!$filename) return false;
// builds s3://somefile.on.amazon.com/file.json
$path = $this->get_json_filename( $filename );
if(!$filename || !file_exists($path)){
return false;
}
elseif(file_exists($path)) {
$data = file_get_contents($path);
}
else $data = false;
return ( empty( $data ) ? false : json_decode( $data , true ));
}
ANSWER: S3 SECURED, REQUIRES SPECIAL URI
Thank you guys for responding in comments. I was WAY off base with this earlier today when I asked this question.
This is the deal, the version of php we are using does not allow for threading. Hence, to ask for multiple URLs you need to use the multi curl option. The s:// somehow worked with a class file for S3 that I missed before. Hence the weird naming.
ALSO, IMPORTANT, if you don't care about protecting the data on S3, you can just make it public and NOT have this issue. In my case the data needs to be somewhat protected so that requires a bunch of things in the URI.
You can use Amazon's S3 class to generate a secure link from the URI and the bucket name on S3. This will return the proper URL to use with your bucket. The S3 class can be downloaded manually or installed via composer in laravel for example. It requires that you install an user with a key to access this in the AWS console.
$bucketName = "my-amazon-bucket";
$uri = "/somefile.txt"
$secure_url = $s3->getObjectUrl($bucketName, $uri, '+5 minutes');
This will generate a valid URL to access the file on S3 which can be used with curl etc..
https://domain.s3.amazonaws.com/bucket/filename.zip?AWSAccessKeyId=myaccesskey&Expires=1305311393&Signature=mysignature

Listing files using wildcards with Laravel Storage and AWS S3

I am converting a Laravel (5.3) app to use AWS S3 as image storage. I need to programmatically get list of images whose names comply with a specific mask (eg 'FS_1054_*.JPG') which when I used local storage I could do easily with the glob() function.
Any suggestions as to how I could do this with S3?
Suppose If you want to get all files then you can use this
Storage::disk('s3')->allFiles('');
It will return All file that have in your bucket. but if you want to look particular then
Storage::disk('s3')->allFiles('FolderName');
or
Storage::disk('s3')->allFiles('FolderName/2FolderName');
have a look of this image. when you want to look all files.
$storage = Storage::disk('s3');
$client = $storage->getAdapter()->getClient();
$command = $client->getCommand('ListObjects');
$command['Bucket'] = $storage->getAdapter()->getBucket();
$command['Prefix'] = 'path/to/FS_1054_';
$result = $client->execute($command);
foreach ($result['Contents'] as $file) {
//do something with $file['Key']
}
I have found an answer, though am happy to know if there is a better one.
Use Storage::files(folder_name) to list all files in the folder, this returns an array. Then use array_where and starts_with to filter the list:
$files = Storage::files(folder_name);
$files = array_where($files, function ($value, $key) use ($mask) {
return starts_with(basename($value), $mask);
});
Try creating subfolders based on the filename as the "index" by which you need to search, so you have something like:
s3://bucket/foo/bar/FS_1054/FS_1054_123.jpg
s3://bucket/foo/bar/FS_1054/FS_1054_124.jpg
s3://bucket/foo/bar/FS_1055/FS_1055_123.jpg
s3://bucket/foo/bar/FS_1055/FS_1055_124.jpg
etc...
So you can get the list using
Storage::disk('s3')->files('foo/bar/FS_1054')
Depending on how fine-grained you want to be able to search, you might need more nested folders:
s3://bucket/foo/bar/FS/1054/FS_1054_123.jpg
s3://bucket/foo/bar/FS/1054/FS_1054_124.jpg
s3://bucket/foo/bar/FS/1055/FS_1055_123.jpg
s3://bucket/foo/bar/FS/1055/FS_1055_124.jpg
s3://bucket/foo/bar/FT/1054/FT_1054_123.jpg
s3://bucket/foo/bar/FT/1054/FT_1054_124.jpg
s3://bucket/foo/bar/FT/1055/FT_1055_123.jpg
s3://bucket/foo/bar/FT/1055/FT_1055_124.jpg
etc...
Though this would allow you to:
Storage::disk('s3')->allFiles('foo/bar/FS')
(note: allFiles() used for recursive listing)
and
Storage::disk('s3')->files('foo/bar/FS/1054')

What in the world of facebook is rsrc.php?

http://static.ak.fbcdn.net/rsrc.php/117600/css/base.css
http://static.ak.fbcdn.net/rsrc.php/z4HBM/hash/3krgnmig.swf
http://b.static.ak.fbcdn.net/rsrc.php/z23ZQ/hash/3ls2fki5.xml
http://static.ak.fbcdn.net/rsrc.php/z7O0P/hash/4hw14aet.png
What does rsrc.php really does? I know that rsrc stands for resource and rsrc.php/z[random]/hash or css/file.extenstion loads a file from somehwere.
Assuming /hash/ or /css/ is a folder which keeps the files like .xml .png .swf but whats with z[random] thing and why they want to load a file from a php? Is it for something like version control for the file or what? If so how to do it (in a simpler way)?
rsrc.php is used by Facebook for version control of all static files, especially images, javascript, and stylesheets. This allows Facebook to apply changes to the main application stack including changes to static content files without breaking functionality for users who are running off an old cached version. It is built into the Facebook architecture as part of the Haste system.
Reference To Code Function Identification By Original Developer
Recommended Process For Managing Static Resources (phabricator.com)
I think that these files are stored in a database. Anything after the SELF (script name, in this case the script is rsrc.php) is passed to the script as a param for the database. I use myself on image files, you base64 the image, store it in the database and usually with a bit of mod_rewrite magic your can get the url of the image to be youtsite.com/images/fish-with-wings when it is really doing this: yoursite.com/some-script.php/fish-with-wings which is really telling the database to look look for get the image from the database where title is = fish-with-wings, and it spits out the base64 for that file.
The advantages of having everything in the database are that for content writers its easier to reference a file and you can delete or purge, or even modify with some cool AJAX and it's also useful to stop hotlinking, which facebook hasn't done here but you could say, if the url is the the full path the redirect to a hotlink warning.
There is a my version of rsrc.php
$request = basename($_SERVER[REQUEST_URI]);
$dotIndex = strrpos($request, ".");
$extension = substr($request, $dotIndex+1);
switch ($extension):
case 'js': $content_type="application/javascript"; break;
default: $content_type="text/css"; break;
endswitch;
$file = Gdecode($request);
$script_file = dirname(__FILE__)."/".$extension."/".$file.".".$extension;
$fp = #fopen($script_file, "r");
if($fp):
fclose($fp);
header('Content-type: '.$content_type);
echo file_get_contents($script_file);
endif;
Don't think it's related to CDN purposes, woulden't make sense running it through an "static" service to serve up dynamic generated content.
I do think however this might be used to hold an open connection, and push data through for facebook updates, ( that's where the xml would make sense for me ).
All of script/css files of Facebook are stored in database and Facebook uses rsrc.php to get them.
rsrc.php code may look like this:
$request = basename($_SERVER["REQUEST_URI"])
if($request != " ") {
$sql = "SELECT * FROM scripts";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
header('Content-type: '.$row["type"]);
echo $row["script"];
}
}
}

Categories