I am able to display and download files uploaded to the server using the media view.
function view($id) {
$this->view = 'Media';
$params = array('id' => $photo['url'], 'name' => $photo['name'], 'download' => false, 'extension' => 'png', 'path' => 'files' . DS . 'user' . DS . $user['id']);
$this->set($params);
}
But I also have an option where users can update a url(like amazon s3) of the file. Is there any way I can update the path (in the above function) to display the file.
I appreciate all your help.
Thanks
No, because either your server is serving those files, or s3 (for example) does.
So you have two options, and I'm using s3 for the example:
either download the file from s3 to your server and serve it yourself via Media
or, redirect the request to s3. For downloads you can set the Content-Type and Content-Disposition by appending &response-content-type=application/octet-stream&response-content-disposition=attachment to the url, but you can't change the filename like you can with Media
Related
I have a flutter form which contains both textual data and an image. I am using http package to send post request to the Laravel backend that has a route in api.php like:
Route::post('/locations', 'LocationController#store');
So at first since I have never tried to upload an image to laravel I had to disable my image input just to check if things were working and and I was successfully able to send a post request from my frontend with a status code of 201 Created with the record successfully created in the database. So I have added the first two lines below in my controller to save the image which are causing my requests to fail with 500 | server error. (The rest lines were already available and working with previous requests):
public function store(Request $request)
{
$locationName = $request["name"];
$data = base64_decode($request["image"]); // Image sent from flutter like: _image != null ? base64Encode(_image.readAsBytesSync()) : ''
Storage::disk('public_images')->put("${$locationName}.jpg", $data); // public_images is defined below
return location::create([
'name' => $request["name"],
'time' => $request["time"],
'package' => $request["package"],
'summary' => $request["summary"],
'info' => $request["info"],
'image' => $request["image"]
]);
}
I have defined the public_images disk(in config/filesystems.php) as follows: (I have to save in the public directory because my server doesn't work with symlinks, but that isn't my problem):
'public_images' => [
'driver' => 'local',
'root' => public_path() . '/images',
],
Now What I want is to save the image to the disk and get the path to store it to the database table so that when accessing from flutter I will only use the api url along with that path to display the image as a network resource. So what is the right way to upload a file from flutter app to laravel backend? Or am I doing it all wrong?
Also: since I am new to file uploads in laravel from flutter, what generally are the best practices in uploading files to a laravel server? Thanks in advance!
You may want to check if request object has any file and the file is valid, then store the file in public directory and store the uri in db.
if($request->hasFile('image') && $request->file('image')->isValid()){
$file = $request->file('image');
$filePath = str_replace('public/', '', $file->storeAs('public/dir', 'name.' . $file->guessExtension()));
}
now with Laravel baseUrl helper you can generate the full path of stored file and using for loading, streaming or force to download.
I am trying to download a file that I stored on S3 to my local Laravel installation to manipulate it. Would appreciate some help.
I have the config data set up correctly because I am able to upload it without any trouble. I am saving it in S3 with following pattern "user->id / media->id.mp3" --> note the fact that I am not just dumping files on S3, I am saving them in directories.
After successfully uploading the file to S3 I update the save path in my DB to show "user->id / media->id.mp3", not some long public url (is that wrong)?
When I later go back to try and download the file I am getting a FileNotFoundException at S3. I'm doing this.
$audio = Storage::disk('s3')->get($media->location);
The weird thing is that in the exception it shows the resource that it cannot fetch but when I place that same url in a browser it displays the file without any trouble at all. Why can't the file system get the file?
I have tried to do a "has" check before the "get" and the has check comes up false.
Do I need to save the full public URL in the database for this to work? I tried that and it didn't help. I feel like I am missing something very simple and it is making me crazy!!
Late answer but important for others,
$s3_file = Storage::disk('s3')->get(request()->file);
$s3 = Storage::disk('public');
$s3->put("./file_name.tif", $s3_file);
The response of $s3_file will be a stream, you can save that stream data to file using Laravel put file method, you will find this stream file in storage/public directory.
You can give your Content-Type as desired and Content-Disposition as 'attachment' because your files are coming from S3 and you have to download it as an attachment.
$event_data = $this->ticket->where('user_id', $user_id)->first();
$data = $event_data->pdf;
$get_ticket = 'tickets/'. $data;
$file_name = "YOUR_DESIRED_NAME.pdf";
$headers = [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'. $file_name .'"',
];
return \Response::make(Storage::disk('s3')->get($get_ticket), 200, $headers);
Say, you have AWS S3 as your default storage.
And you want to download my_file.txt from S3 to my_laravel_project\storage\app\my_file.txt
And you want to make it a one-liner
Storage::disk('local')->put('my_file.txt', Storage::get('my_file.txt'));
I have a website here http://www.voclr.it/acapellas/ my files are hosting on my Amazon S3 Account, but when a visitor goes to download an MP3 from my website it forces them to stream it but what I actually want it to do is download it to there desktop.
I have disabled S3 on the website for now, so the downloads are working fine. but really I want S3 to search the MP3s
Basically, you have to tell S3 to override the content-disposition header of the response. You can do that by appending the response-content-disposition query string parameter to the S3 file url and setting it to the desired content-disposition value. To force download try:
<url>&response-content-disposition="attachment; filename=somefilename"
You can find this in the S3 docs. For information on the values that the content-disposition header can assume you can look here.
As an additional information this also works with Google Cloud Storage.
require_once '../sdk-1.4.2.1/sdk.class.php';
// Instantiate the class
$s3 = new AmazonS3();
// Copy object over itself and modify headers
$response = $s3->copy_object(
array( // Source
'bucket' => 'your_bucket',
'filename' => 'Key/To/YourFile'
),
array( // Destination
'bucket' => 'your_bucket',
'filename' => 'Key/To/YourFile'
),
array( // Optional parameters
**'headers' => array(
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment'**
)
)
);
// Success?
var_dump($response->isOK());
Amazon AWS S3 to Force Download Mp3 File instead of Stream It
I created a solution for doing this via CloudFront functions (no php required since it all runs at AWS by linking to the .mp3 file on Cloudfront with a ?title=TitleGoesHere querystring to force a downloaded file with that filename). This is a fairly recent way of doing things (as of August 2022). I documented my function and how I set up my "S3 bucket behind a CloudFront Distribution" here: https://stackoverflow.com/a/73451456/19823883
The problem I have is that I need the Content-Disposition: attachment header to be present on EVERY file that hits my bucket.
In Wordpress, I can just use .htaccess to cover the filetypes in question (videos), but those rules do not extend to my S3 downloads which browsers are simply trying to open, instead of download.
I need an automated/default solution, since I am not the only one that uploads these files (our staff uploads through Wordpress, and the uploads all are stored on our S3 bucket). So using Cloudberry or other browsers is not useful for this situation. I can't adjust the files on a per-file basis (the uploads are too frequent).
Is there a way to do this?
(Other information: I'm using the "Amazon S3 and Cloudfront" plugin on Wordpress that is responsible for linking the two together. Unfortunately, the site is not public, so I cannot link to it.)
Unfortunately there is no way to set this for an entire bucket in S3, and also Cloudfront can only set Cache-Headers
But you can set The Content-disposition parameter when uploading files to S3.
For existing files, you must change the Header, so loop through every object in the Bucket, and copy it to itself using the new headers.
All I can say now, please post the code that uploads the file to S3.
First, you need to locate the code that puts the object in the bucket.
You can use notepad++ to search for "putObject" within the php files of whatever plugin you are using.
An example code from another WP plugin that stores files to S3 is as follows:
$this->s3->putObject( array(
'Bucket' => $bucket,
'Key' => $file['name'],
'SourceFile' => $file['file'],
) );
Now, simply add ContentDisposition' => 'attachment' like so:
$this->s3->putObject( array(
'Bucket' => $bucket,
'Key' => $file['name'],
'SourceFile' => $file['file'],
'ContentDisposition' => 'attachment',
) );
Thats it :)
Yes, you can set default Content-Disposition header for your each and every upcoming uploading file in your S3 bucket using Bucket Explorer's Bucket Default feature.
For existing files, you can use Update Metadata option that update metadata on every file exist in your bucket in batch.
You just need to -
Select Key as : Content-Disposition
Add Value as : attachment;filename={$file_name_without_path_$$}
Then update metadata on the files.
See this page to set Content-Disposition on your file.
More references:
http://www.bucketexplorer.com/documentation/amazon-s3--metadata-http-header-bucket-default-metadata.html
http://www.bucketexplorer.com/documentation/amazon-s3--how-to-manage-http-headers-for-amazon-s3-objects.html
http://www.bucketexplorer.com/documentation/amazon-s3--metadata-http-header-update-custom-metadata.html
Thanks
I am using amazon S3 service with PHP by using this API
https://github.com/tpyo/amazon-s3-php-class
I am passing the url to client like this
https://domain.s3.amazonaws.com/bucket/filename_11052011111924.zip?AWSAccessKeyId=myaccesskey&Expires=1305311393&Signature=mysignature
So when the client clicks or paste the URL into browser , the file downloaded with the name of filename_11052011111924.zip.But I stored my original filename in DB.
So is it possible to download when passing the URL alone to the client and download with original file name.I am not sure whether this will help me.
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
If you set the headers that you listed on your file when you upload it to S3, you will be able to download the file with the original filename. (you can also set these on existing files in S3 - see the AWS docs)
I'm not sure if your library supports this but you can do it with the AWS S3 SDK.
Something like (I don't know php so check the syntax):
// Instantiate the class
$s3 = new AmazonS3();
$response = $s3->create_object('bucket', 'filename_11052011111924.zip', array(
'fileUpload' => 'filename.zip',
'contentType' => 'application/octet-stream',
'headers' => array( // raw headers
'Content-Disposition' => 'attachment; filename=filename.zip',
),
));
Update
You can also adjust certain headers each time you generate a new url. See http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=AmazonS3/get_object_url
$url = $s3->get_object_url('bucket', 'filename_11052011111924.zip', '5 minutes', array(
'response' => array(
'Content-Disposition' => 'attachment; filename=filename.zip'
)
));
I don't think that will work (I never tried it though). You might need to download the file to your server first, later use headers, once it is completed (or after sometime later with some bot or cron) you can delete the file(s).
This approach will be using your bandwidth.
Yes, you can tell to AWS how output file must be named:
Note: we encode file name!
$filename = "Here we can have some utf8 chars.ext";
$outputFileName = '=?UTF-8?B?' . base64_encode($filename) . '?=';
$url = $s3->get_object_url(
'bucket_name',
'path_to_the_file.ext',
'5 minutes',
array(
'response' => array(
'content-disposition' => 'attachment;' . " filename=\"" . $outputFileName . "\";")
)
)
);