laravel s3 signed url does not work with pdf - laravel

I have recently added s3 as a storage to my laravel application. I use signed url which works perfectly with uploaded images, but it does not with pdfs. I receive access denied, for the pdfs. If I make the files public via S3 console, I can receive it.
I am uploading these files with this mehtid:
Storage::disk('s3')->put();
I have tried signing the url with these two methods:
$url = Storage::disk('s3')->temporaryUrl(
$path, Carbon::now()->addMinutes(5)
);
$s3 = \Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$expiry = "+10 minutes";
$command = $client->getCommand('GetObject', [
'Bucket' => \Config::get('filesystems.disks.s3.bucket'),
'Key' => $path,
]);
$request = $client->createPresignedRequest($command, $expiry);
return (string) $request->getUri();
Any help would be appriciated!

I found out the solution.
The problem was, when I gave the url to pdf.js, it automatically changed "&" chars in the url to "&" , and s3 didnt recognize this url. I solved it using js string replace method
var pdfUrl = '{{\App\Models\DataHelper::getImgUrl($note->file)}}'; //getting the singed url
pdfUrl = pdfUrl.replaceAll("&", '&');
showPDF(pdfUrl); //pdf.js

Related

Laravel: how to upload pdf file directly to Google Cloud Storage bucket without first saving it locally

I am using the google/cloud-storage package in an API and successfully uploading pdf files to a Google Cloud Storage bucket. However, the pdf files are first saved locally before they are uploaded to the Google Cloud Storage bucket.
How can I skip saving them locally and instead upload them directly to the Google Cloud Storage bucket? I am planning to host the API on Google App Engine.
This is the post for it.
This is what I am doing currently:
$filename = $request['firstname'] . '.pdf';
$fileStoragePath = '/storage/pdf/' . $filename;
$publicPath = public_path($fileStoragePath);
$pdf = App::make('dompdf.wrapper');
$pdf->loadView('pdfdocument', $validatedData)
$pdf->save($publicPath);
$googleConfigFile = file_get_contents(config_path('googlecloud.json'));
$storage = new StorageClient([
'keyFile' => json_decode($googleConfigFile, true)
]);
$storageBucketName = config('googlecloud.storage_bucket');
$bucket = $storage->bucket($storageBucketName);
$fileSource = fopen($publicPath, 'r');
$newFolderName = $request['firstname'].'_'.date("Y-m-d").'_'.date("H:i:s");
$googleCloudStoragePath = $newFolderName.'/'.$filename;
/*
* Upload a file to the bucket.
* Using Predefined ACLs to manage object permissions, you may
* upload a file and give read access to anyone with the URL.
*/
$bucket->upload($fileSource, [
'predefinedAcl' => 'publicRead',
'name' => $googleCloudStoragePath
]);
Is it possible to upload files to a Google Cloud Storage bucket without first saving them locally?
Thank you for your help.
I have not verified this code, but the class PDF member output() returns a string.
$pdf = App::make('dompdf.wrapper');
$pdf->loadView('pdfdocument', $validatedData)
...
$bucket->upload($pdf->output(), [
'predefinedAcl' => 'publicRead',
'name' => $googleCloudStoragePath
]);
You can simply the client code. Replace:
$googleConfigFile = file_get_contents(config_path('googlecloud.json'));
$storage = new StorageClient([
'keyFile' => json_decode($googleConfigFile, true)
]);
with
$storage = new StorageClient([
'keyFilePath' => config_path('googlecloud.json')
]);

How can I get the full URL of file uploaded to s3 with Laravel?

I have this to upload pictures to one bucket on s3 in AWS
$image = $picture;
$ext = explode(";", explode("/",explode(",", $image)[0])[1])[0];
$image = str_replace('data:image/'.$ext.';base64,', '', $image);
$image = str_replace(' ', '+', $image);
$imageName = str_random(10) . '.' . $ext;
$fullImagePath = 'datasheets/' . $imageName;
Storage::disk('s3')->put($fullImagePath, base64_decode($image));
$DataSheetPicture = new DataSheetPicture();
$DataSheetPicture->data_sheet_id = $DataSheet->id;
$DataSheetPicture->picture = Storage::disk('s3')->url($fullImagePath);
$DataSheetPicture->save();
The above code works fine, it uploads the pictures successfully to the bucket, but on this line
$DataSheetPicture->picture = Storage::disk('s3')->url($fullImagePath);
It saves the URL in the database like these
/datasheets/6GcfzgUPrA.jpeg
/datasheets/AuqHmu8p0W.jpeg
But I need get the URL like this
https://s3.REGION.amazonaws.com/BUCKET-NAME/FULL-IMAGE-PATH
I don't want to concatenate the region or the bucket name because it could be dynamic
The following will give you the proper URL:
return Storage::disk('s3')->url($filename);
Since Laravel 5.2 you're also able to use cloud()
return Storage::cloud()->url($filename);
I don't want to concatenate the region or the bucket name because it could be dynamic
Then you must be modifying your config and not doing this manually to work correctly, for example:
config([
'filesystem.disks.s3.bucket' => 'my_bucket',
'filesystem.disks.s3.region' => 'my_region'
]);
If you remove the AWS_URL setting from your .env file, the Storage::disk('s3')->url($fullImagePath) should give you the proper URL that you need
See discussion also here: https://laracasts.com/discuss/channels/laravel/storage-url-from-s3?page=1&replyId=482913

Uploading image file to google cloud using Laravel

Hi i have trying to upload image file to google cloud storage using laravel API.
i have integrated google sdk via composer and i try to hit with postman i am getting the url and get stored in my database but the image file is not uploaded in the folder in google cloud .i created a folder with name 'avatars' in by bucket.
here is my code.
this is my controller
public function updateAvatar (AvatarUploadRequest $request) {
$me = Auth::user();
$disk = Storage::disk('gcs');
$url = $disk->url('avatars'. "/" . $me->uuid . ".jpg");
$me->avatar = $url;
$me->save();
return $this->prepareItem($me);
}
this is my filesystems.php file
'gcs' => [
'driver' => 'gcs',
'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'my-project-id'),
'key_file' => env('GOOGLE_CLOUD_KEY_FILE', null),
'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'my-bucket-name'),
'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null),
'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI',
'https://console.cloud.google.com/storage/browser/my-project-id/'),
],
This all i have done. did i missing anything? any additional configuration needed?
This is because you are generating url but not storing in file in the disk,
here is the code example
fist get file contents from request:
$avatar = $request->file('avatar')
second save it into storage:
Storage::disk('gcs')->put('avatars/'.$me->uuid , $file);
Step 1:First Create an Account in google cloud storage For that you will need credit card details but it won't charge, when we were not gooing for "Upgrade" because this is to make sure that it is not Robot.
Step 2:Create a Project in google cloud storage, here for example Project Name is "My-project".
Step 3: Create a Bucket in the Project "My-project". for example here i created "My-buckets"
Step 4: Create a Folder in the bucket for example here i created a folder name "avatars".
##Step 5: Go to the optinon IAM & Admin => Service accounts => Create Service account => Put Service Account name should ne the Bucket name "my-buckets".=> Check Furnish a new private key and save then a new json file will download and put that file in the project.Here i rename it as my-buckets.json.
Go to The Project in xampp
Step 6: Go to the userController.php
[app->http->controllers->api->v2->userController.php]
$me = Auth::user();
$file = $request->file('avatar');
$name= $me->uuid . ".".$file->getClientOriginalExtension();
$filePath = 'avatars/' . $name;
$disk = Storage::disk('gcs')->put($filePath, file_get_contents($file));
$gcs = Storage::disk('gcs');
$url = $gcs->url('avatars'. "/" . $me->uuid . ".jpg");
$me->avatar = $url;
$me->save();
return $this->prepareItem($me);
}
Step 7: Go to the filesystems.php
[config->filesystems.php]
Set a driver for the google cloud
'gcs' => [
'driver' => 'gcs',
'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'my-project-209405'),
'key_file' => env('GOOGLE_APPLICATION_CREDENTIALS', './my-buckets.json'), // optional: /path/to/service-account.json
'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'my-buckets'),
'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null), // optional: /default/path/to/apply/in/bucket
'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', 'https://storage.googleapis.com/my-buckets/'), // see: Public URLs below
],
Add the Path Of my-buckets.json we got at Step 5 to the Key_file
step 8: Dowload Google SDK Console
Url - https://cloud.google.com/sdk/
step 9: First we dont have the Access to the Account which the google cloud is created ,To get access we need to run google cloud command in google SDK console
Run : gcloud auth login
Then it will open the brouser a asking the gmail account which we created the google cloud storage and allow the permission for google sdk to access, Then it will show the current project that we are, in the console.
step 10: Run the command to enable the public accessibility of the object. The URL that we are getting and stored in the database is not having publicly access
Run : gsutil iam ch allUsers:objectViewer gs://my-buckets
Hope You can Upload your file from the project to the Cloud Storage
Thank You
****Harisankar.H****

Laravel, getting uploaded file's url

I'm currently working on a Laravel 5.5 project, where I want to upload files, and then, I want to get their url back of the file (I have to use it client side).
now my code looks like this:
public function pdfUploader(Request $request)
{
Log::debug('pdfUploader is called. ' . $request);
if ($request->hasFile('file') && $request->file('file')->isValid()) {
$extension = $request->file->extension();
$fileName = 'tmp' . round(microtime(true) * 1000) . '.' . $extension;
$path = $request->file->storeAs('temp', $fileName);
return ['status' => 'OK', 'path' => URL::asset($path)];
}
return ['status' => 'NOT_SAVED'];
}
It works fine, I got back the OK status, and the path, but when I want to use the path, I got HTTP 404. I checked, the file is uploaded fine..
My thought is, I should register the new url in the routes. If I have to, how can I do it dynamically, and if its not necessary what is wrong with my function?
Thx the answers in advance.
By default laravel store all uploaded files into storage directory, for example if you call $request->file->storeAs('temp', 'file.txt'); laravel will create temp folder in storage/app/ and put your file there:
$request->file->storeAs('temp', 'file.txt'); => storage/app/temp/file.txt
$request->file->storeAs('public', 'file.txt'); => storage/app/public/file.txt
However, if you want to make your uploaded files accessible from the web, there are 2 ways to do that:
Move your uploaded file into the public directory
$request->file->move(public_path('temp'), $fileName); // => public/temp/file.txt
URL::asset('temp/'.$fileName); // http://example.com/temp/file.txt
NOTE: make sure that your web server has permissions to write to the public directory
Create a symbolic link from storage directory to public directory
php artisan storage:link
This command will create a symbolic link from public/storage to storage/app/public, in this case we can store our files into storage/app/public and make them accessible from the web via symlinks:
$request->file->storeAs('public', $fileName); // => storage/app/public/file.txt
URL::asset('storage/'.$fileName); // => http://example.com/stoage/file.txt

response::download is doing nothing

I am having problems getting files to download outside of the public folder. Here is the Scenario:
These files cannot be accessed from anywhere but through this application and these downloads must go through access control. So a user can't download the file if they are not logged in and have permission to.
I have a route defined with a get variable. This ID goes into the controller and the controller calls the method below:
public static function downloadFile($id){
$file = FileManager::find($id);
//PDF file is stored under app/storage/files/
$download= app_path().substr($file->location,6);///home/coursesupport/public_html/app/storage/files/fom01/7-2/activities-and-demos.pdf
$fileName = substr($download,strrpos($download,'/')+1);//activities-and-demos.pdf
$mime = mime_content_type($download);//application/pdf
$headers = array(
'Content-Type: '.$mime,
"Content-Description" => "File Transfer",
"Content-Disposition" => "attachment; filename=" . $fileName
);
return Response::download($download, $fileName, $headers);
}
the problem is it does nothing, just opens a blank page. Am I missing something? oh yeah, and the link to the route mentioned above opens a blank tab.
I appreciate any help. Thanks!
It should work by doing only this:
public static function downloadFile($id)
{
$file = FileManager::find($id);
$download= app_path().substr($file->location,6);
$fileName = substr($download,strrpos($download,'/')+1);
return Response::download($download, $fileName);
}
Make sure your route is actually returning the returned response. Eg:
Route::get('download', function()
{
return DownloadHandler::downloadFile(1);
});
Without the return in the route the IlluminateResponse will do nothing.

Resources