How to use Wasabi (AmazonS3) in sabre/dav? - sabredav

I am building a WebDAV server using sabre/dav, I want to create a WebDAV server file storage location in Wasabi which is compatible with AmazonS3, I did some research and found something that looks like AWS.php but I don't know how to use it. If anyone knows how to do this specifically, please respond.
What we tried:
・Download s3dav (https://github.com/audionamix/s3dav) and install the file.
・Server.php was written as follows
<?php
use Sabre\DAV;
use Aws\S3\S3Client;
// The autoloader
require 'vendor/autoload.php';
$raw_credentials = array(
'credentials' => array(
'key' => '<insert-access-key>',
'secret' => '<insert-secret-key>'
),
//'profile' => 'wasabi',
'endpoint' => 'https://s3.wasabisys.com',
'region' => 'us-east-1',
'version' => 'latest',
'use_path_style_endpoint' => true,
'use_path_style' => true,
'use_ssl' => true,
'port' => 443,
'hostname' => 's3.wasabisys.com',
'bucket' => '<bucket-name>',
);
// establish an S3 Client.
$s3 = S3Client::factory($raw_credentials);
// Now we're creating a whole bunch of objects
//$rootDirectory = new DAV\FS\Directory('public');
$rootDirectory = new DAV\FS\S3Directory("/",'<bucket-name>',$s3);
// The server object is responsible for making sense out of the WebDAV protocol
$server = new DAV\Server($rootDirectory);
// If your server is not on your webroot, make sure the following line has the
// correct information
$server->setBaseUri('/server.php/');
// The lock manager is reponsible for making sure users don't overwrite
// each others changes.
$lockBackend = new DAV\Locks\Backend\File('data/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
// This ensures that we get a pretty index in the browser, but it is
// optional.
$server->addPlugin(new DAV\Browser\Plugin());
// All we need to do now, is to fire up the server
$server->exec();
Result:
The file name list is displayed, but it is displayed as 0 bytes.
Uploading is working, but other operations are not working (file size is correct on Wasabi).
”4.4.0 Exception Cannot traverse an already closed generator" is displayed.

Related

Access Custom S3 Metadata After Completing Multipart Upload

I'm wanting to access the custom metadata for an object uploaded via the S3 multipart upload after firing off the completeMultipartUpload method.
I initiate a multipart S3 upload with some added custom metadata like so:
$response = $this->client->createMultipartUpload([
'Bucket' => $this->bucket,
'Key' => $key,
'ContentType' => $type,
'Expires' => 60,
'Metadata' => [
'file-guid' => $fileGuid,
],
]);
When I complete the multipart upload, I'm wanting to access the file-guid metadata and pass it along in my response.
$result = $this->client->completeMultipartUpload([
'Bucket' => $this->bucket,
'Key' => $key,
'UploadId' => $uploadId,
'MultipartUpload' => [
'Parts' => $parts,
],
]);
$fileGuid = $result['?'] // Couldn't find the metadata in the result.
return response()->json(['file-guid' => $fileGuid]);
I've checked the S3 object after it's been uploaded and it shows the custom metadata, but I don't see how to access it. I assumed it would be part of the completeMultipartUpload response, but I'm not seeing it.
Any help would be appreciated. Thanks!
I found a solution, but it involves an additional request. If anyone knows of a way to access the metadata without making another request, that would be better.
$headObject = $this->client->headObject([
'Bucket' => $this->bucket,
'Key' => $key,
]);

reading a file from s3 bucket with laravel getting error

Im trying to get file from s3 bucket using getObject
$s3 = AWS::createClient('s3');
$file = $s3->getObject(array(
'Bucket' => 'hotel4cast',
'Key' => $path->path,
'SaveAs' => public_path()
));
I'm getting below error
Error executing
"GetObject" on "https://s3.amazonaws.com/mybucket/filename.xlsx";
AWS HTTP error: Unable to open /var/www/html/laravel/public/ using mode r+: fopen(/var/www/html/laravel/public/):
ailed to open stream: Is a directory
if i take SaveAs out and dump $file i get object of data, body, stream all that stuff but not sure what to do with that.
I have figured out, there is bug in aws sdk,
i was able to get file to save by storing path in var before calling getObject
$r = fopen(public_path() . '/myfile.xlsx', 'wb');
$s3 = AWS::createClient('s3');
$file = $s3->getObject(array(
'Bucket' => 'bucketname',
'Key' => $path->path,
'SaveAs' => $r
));
can you tell me that what exactly these equals too ? So, I can guide you accordingly.
$path->path = ???
public_path() = ???
Edited
your method params should be like this, you just passing the saveAs path but attaching the key name, So, add the keyname with saveAs path, it will be downloaded.
$s3 = AWS::createClient('s3');
$file = $s3->getObject(array(
'Bucket' => 'hotel4cast',
'Key' => $path->path,
'SaveAs' => public_path()."/filename.xlsx"
));
here are the examples of code, which I am using for uploading file and coping file
for uploading
$result = $this->S3->putObject([
'ACL' => 'public-read-write',
'Bucket' => 'xyz', // REQUIRED
'Key' => 'file.xlsx', // REQUIRED
'SourceFile' => public_path()."/xlsx/file.xlsx",
]);
for Coping from one bucket to another
$copy = $this->S3->copyObject(array(
'ACL' => 'public-read-write',
'Bucket' => 'xyz', // REQUIRED
'Key' => 'file.xlsx', // REQUIRED
'CopySource' => 'mybucketname/xlsx/file.xlsx,
));
but your file which is exists in s3 bucket should have permission to read. other wise it will give you error to saveAs, copy etc
here are multiple permissions, you can see here
'ACL' => 'private|public-read|public-read-write|authenticated-read|aws-exec-read|bucket-owner-read|bucket-owner-full-control',

How to manage database settings in Yii while running?

I want to let user manage database connection settings from website itself. I've thought that I would save db setting in a txt file and before every connection these would be read from this file first. Is it even possible?
I tried to use this in the main config file, but it does not work:
$myfile = Yii::app()->file->set('assets/settings.txt', true);
$array = explode("\r\n", $myfile->getContents());
$dblink = $array[0];
...
'db' => array(
'connectionString' => $dblink,
...

RavenDB Query: Have to use Customize() instead of Include()

I'm getting an error that I'm exceeding the number of requests allowed per session (30) when using this query (using Include instead of Customize):
ApplicationServer appServer = QuerySingleResultAndSetEtag(session => session
.Include<ApplicationServer>(x => x.CustomVariableGroupIds)
.Include<ApplicationServer>(x => x.ApplicationIdsForAllAppWithGroups)
.Include<ApplicationServer>(x => x.CustomVariableGroupIdsForAllAppWithGroups)
.Include<ApplicationServer>(x => x.CustomVariableGroupIdsForGroupsWithinApps)
.Include<ApplicationServer>(x => x.InstallationEnvironmentId)
.Load <ApplicationServer>(id))
as ApplicationServer;
Note, the error occurs on this line, which is called for each AppWithGroup within an application:
appGroup.Application = QuerySingleResultAndSetEtag(session =>
session.Load<Application>(appGroup.ApplicationId)) as Application;
However, this query (using Customize) doesn't create extra requests:
ApplicationServer appServer = QuerySingleResultAndSetEtag(session =>
session.Query<ApplicationServer>()
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIds))
.Customize(x => x.Include<ApplicationServer>(y => y.ApplicationIdsForAllAppWithGroups))
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIdsForAllAppWithGroups))
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIdsForGroupsWithinApps))
.Customize(x => x.Include<ApplicationServer>(y => y.InstallationEnvironmentId))
.Where(server => server.Id == id).FirstOrDefault())
as ApplicationServer;
However, the above query causes an error:
Attempt to query by id only is blocked, you should use call
session.Load("applications/2017"); instead of
session.Query().Where(x=>x.Id == "applications/2017");
You can turn this error off by specifying
documentStore.Conventions.AllowQueriesOnId = true;, but that is not
recommend and provided for backward compatibility reasons only.
I had to set AllowQueriesOnId = true because it was the only way I could get this to work.
What am I doing wrong in the first query to cause the includes not to work?
By the way, another post had the same issue where he had to use Customize. I'd like to do this correctly though.
I'm not sure why the load isn't doing this for you, What version of raven are you on? I just tested this in Raven 2.5 build 2700 and the include is bringing back the information for me in a single request.
Anyway, with the load not working quite like i would expect, i would switch to a set of lazy queries to get what you want in 2 server round trips. http://ravendb.net/docs/2.5/client-api/querying/lazy-operations.
Another option that might work out better for you, (depending on what you are really doing with all of that data) is a transformer. http://ravendb.net/docs/2.5/client-api/querying/results-transformation/result-transformers?version=2.5
Hope that helps.

How to use Amazon RDS with Kohana's ORM

Is there any way to use Kohana's ORM with Amazon RDS?
I found the Amazon PHP SDK but I'm not sure how to plug it into Kohana so that the ORM uses it. I also couldn't find any Kohana module for Amazon RDS. Any suggestion?
Yes, this is absolutely possible. I have this exact configuration for my website.
In your AWS management console, you will need to get the "endpoint" of your RDS server. The name is quite long and begins with the name of your DB instance. (See the code below for example)
Next, open your database configuration file: application/config/database.php
In the 'default' configuration, change your hostname to the endpoint. Also change the database, username and password to whatever yours is set up with:
'default' => array
(
'type' => 'mysql',
'connection' => array(
/**
* The following options are available for MySQL:
*
* string hostname server hostname, or socket
* string database database name
* string username database username
* string password database password
* boolean persistent use persistent connections?
*
* Ports and sockets may be appended to the hostname.
*/
'hostname' => 'your-db-instance.njgo7sn43.us-east-1.rds.amazonaws.com',
'database' => 'db_name',
'username' => 'username',
'password' => 'SuperCaliFrajilisticExpiAliDocious',
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
'profiling' => TRUE,
),
Also, in your application/bootstrap.php file, make sure to UN-comment the database module:
Kohana::modules(array(
'database' => MODPATH.'database', // Database access
'orm' => MODPATH.'orm', // Object Relationship Mapping
));
The ORM module is optional but very nice to use.
Hope this helps!