renaming a file before uploading to digital ocean spaces using laravel - laravel

To upload a file I use
Storage::disk('spaces')->putFile('uploads', $request->file, 'public');
The file is saved successfully on digital ocean spaces. But I want to rename it to something like this user_1_some_random_string.jpg. And then save it.
How can I do it?

The move method may be used to rename or move an existing file to a new location:
Storage::move('hodor/oldfile-name.jpg', 'hodor/newfile-name.jpg');
Also:
If you would not like a file name to be automatically assigned to your stored file, you may use the storeAs method, which receives the path, the file name, and the (optional) disk as its arguments:
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
More: https://laravel.com/docs/5.6/filesystem

try use rand()
$ext = $request->file('file')->getClientOriginalExtension();
$name = rand(11111,99999).'.'.$ext;
Storage::disk('spaces')->putFile('uploads', $name, 'public');

This is pretty old but I found an answer for anyone still looking.
You need to use the method putFileAs, as far as I can see
the first parameter is the bucket/location. I tested this and it will create a new folder if you use 'uploads/testz' it created the 'testz' in the uploads folder on spaces.
the second parameter is the request file object, in my case $request->file('file')
the third parameter is the filename that you WANT to store the file as. I tested and if you 'testz/<yourspecialfilename.extension>' it will create the same folder as in parameter 1, which suggests to me that the method concats param 1 and 3.
So the full snippet in my controller is
public function create(Request $request){ Storage::disk('spaces')->putFileAs('uploads/testz', $request->file('file'), 'mychosenfilename.mydesiredextension');
return redirect()->back();}

Related

Set Filename Storage::put

I cant set a filename with Storage::put in Laravel 5.8
I tried the following:
Storage::put(private/foo/bar , $file, 'private');
This is creating the folder structure with a random generated filename inside. (Like: private/foo/bar/uidjasbknfsdoiruewjnfsdai.pdf)
Storage::put(private/foo/bar/file.pdf , $file, 'private');
This is creating this: private/foo/bar/file.pdf/uidjasbknfsdoiruewjnfsdai.pdf
I expect my own given filename on this private file. The file should not be public.
According to Laravel docs:
If you would not like a file name to be automatically assigned to your stored file, you may use the storeAs method, which receives the path, the file name, and the (optional) disk as its arguments:
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
You may also use the putFileAs method on the Storage facade, which will perform the same file manipulation as the example above:
$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
The third argument for the putFileAs is the visibility of the file. If you would like every users can access it, use public instead of $request->user()->id.
You can read more here.

Laravel 5.5 Storage::url() doesn't return the desired url with S3

I'm using S3 for storage in my laravel 5.5 project
Everything is good and the images is stored in my bucket under my desired folder
using :
use Illuminate\Support\Facades\Storage;
$path = Storage::put($directory, $file, $permission);
$fullPath = config('filesystems.disks.s3.driver').
'.'.
config('filesystems.disks.s3.region').
'.amazonaws.com/'.
config('filesystems.disks.s3.bucket').
'/'.
$path;
the full path then will be like :
https://s3.us-east-2.amazonaws.com/iva-files/brands/logos/qweisiEC7H2SOV9ozjuOOBRxw399cTm2imnbJEXj.jpeg
I searched for better way to get my full url so I found:
Storage::url($path);
But it's returning path like :
https://ivasystem.signin.aws.amazon.com/console/brands/logos
What's wrong with my sinario ?
Try:
Storage::disk('s3')->url($filename)
As mentioned in the Official Laravel Documents
The path to the file will be returned by the putFile method so you can store the path, including the generated file name, in your database.
So you should always store file path & file name in database columns so that later on you can concatenate path & name to get fill url to the file.
In my project I am already doing this.

Laravel 5: How do you copy a local file to Amazon S3?

I'm writing code in Laravel 5 to periodically backup a MySQL database. My code thus far looks like this:
$filename = 'database_backup_'.date('G_a_m_d_y').'.sql';
$destination = storage_path() . '/backups/';
$database = \Config::get('database.connections.mysql.database');
$username = \Config::get('database.connections.mysql.username');
$password = \Config::get('database.connections.mysql.password');
$sql = "mysqldump $database --password=$password --user=$username --single-transaction >$destination" . $filename;
$result = exec($sql, $output); // TODO: check $result
// Copy database dump to S3
$disk = \Storage::disk('s3');
// ????????????????????????????????
// What goes here?
// ????????????????????????????????
I've seen solutions online that would suggest I do something like:
$disk->put('my/bucket/' . $filename, file_get_contents($destination . $filename));
However, for large files, isn't it wasteful to use file_get_contents()? Are there any better solutions?
There is a way to copy files without needing to load the file contents into memory using MountManager.
You will also need to import the following:
use League\Flysystem\MountManager;
Now you can copy the file like so:
$mountManager = new MountManager([
's3' => \Storage::disk('s3')->getDriver(),
'local' => \Storage::disk('local')->getDriver(),
]);
$mountManager->copy('s3://path/to/file.txt', 'local://path/to/output/file.txt');
You can always use a file resource to stream the file (advisable for large files) by doing something like this:
Storage::disk('s3')->put('my/bucket/' . $filename, fopen('path/to/local/file', 'r+'));
An alternative suggestion is proposed here. It uses Laravel's Storage facade to read the stream. The basic idea is something like this:
$inputStream = Storage::disk('local')->getDriver()->readStream('/path/to/file');
$destination = Storage::disk('s3')->getDriver()->getAdapter()->getPathPrefix().'/my/bucket/';
Storage::disk('s3')->getDriver()->putStream($destination, $inputStream);
You can try this code
$contents = Storage::get($file);
Storage::disk('s3')->put($newfile,$contents);
As Laravel document this is the easy way I found to copy data between two disks
Laravel has now putFile and putFileAs method to allow stream of file.
Automatic Streaming
If you would like Laravel to automatically manage
streaming a given file to your storage location, you may use the
putFile or putFileAs method. This method accepts either a
Illuminate\Http\File or Illuminate\Http\UploadedFile instance and will
automatically stream the file to your desired location:
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
// Automatically generate a unique ID for file name...
Storage::putFile('photos', new File('/path/to/photo'));
// Manually specify a file name...
Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');
Link to doc: https://laravel.com/docs/5.8/filesystem (Automatic Streaming)
Hope it helps
Looking at the documentation the only way is using method put which needs file content. There is no method to copy file between 2 file systems so probably the solution you gave is at the moment the only one.
If you think about it, finally when copying file from local file system to s3, you need to have file content to put it in S3, so indeed it's not so wasteful in my opinion.
I solved it in the following way:
$contents = \File::get($destination);
\Storage::disk('s3')
->put($s3Destination,$contents);
Sometimes we don't get the data using $contents = Storage::get($file); - storage function so we have to give root path of the data using Laravel File instead of storage path using Storage.

Laravel downloads a file with unknown type

I am using Laravel 4. I allow users to upload a file, which is programmatically renamed with some number and stored. I also allow them to download the files, though I am supposed to rename their file from some funny number to their name, and download it.
My problem is, how can I change filename just before its downloaded?
My code:
return Response::download($pathToFile, $name);
When I do that, the file is downloaded with unknown format.
The second $name parameter, needs to include the full filename (including the file extension). The download method does not automatically detect the extension from the file path and append it to the name, so that needs to be done manually. Something like this will work:
return Response::download(
$pathToFile,
$name . '.' . pathinfo($pathToFile, PATHINFO_EXTENSION)
);

How do I get the full local path of a file uploaded with $_FILES

I am uploaded a file through the file input. If I print_r($_FILES), I can get several pieces of info, but it doesn't give me the full LOCAL path of the file (the path on my computer, not the server). How do I get this?
I need this to use the FTP library in CodeIgniter. Documentation is here on how to use it to upload a file.
As you can see, it requires the full local path, although I'm not sure why.
As file upload path is a variable which changes from server to server, I would suggest you to use move_uploaded_file() function:
$target = "uploads/myfile.something";
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target)) {
// do something
}
that way it will always work no matter what the path is even if it changes. The target can be anything you wish, it's relative to the current folder where script is being executed.
I solved this.
public function upload($file, $folder) {
$this->CI->ftp->upload($_FILES['file']['tmp_name'], '/public_html/rest/of/path/' . $_FILES['file']['name'], 'ascii', 0775);
}
The file is being uploaded, so you can access it with $FILES['file']['tmp_name']. This is from within a class, so that's why I'm using $this->CI. Otherwise, I would just use $this.

Resources