Amazon AWS S3 to Force Download Mp3 File instead of Stream It - amazon-s3

I'm using Amazon S3 to put the mp3 file then allow our site visitor to download the mp3 from Amazon AWS. I use S3Fox to manage the file, everything seems working fine until recently we got many complaints from visitor that the mp3 was streamed via the browser instead of displaying browser save dialog.
I try for some mp3 and notice that for some mp3, the save dialog box is appear, and for some others they're streamed via browser. What can I do to force that the mp3 file will be downloaded instead of streamed via web browser....
Any help would be much appreciated.
Thanks

In order to do so you need to set the Content-Disposition header:
Content-disposition: attachment; filename=song.mp3
I don't think this is possible with S3Fox. You could use Bucket Explorer (not free) or write a script to upload the files.

Ok, it's been a long time since you ask this, but I had the same problem and I'd like to share my solution with the community, just in case someone else need to solve this thing. Of course, you can change Content-Type and Content-Disposition from the Amazon S3 Console, but the interesting thing is to do it programmatically.
The following code works fine for me:
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());
Hope it can helps other struggling with the same trouble.

This ended up being my solution for force downloading files from AWS S3.
In safari the files were downloading as .html files until I stopped returning the readfile and just ran the function alone.
public function get_download($upload_id)
{
try {
$upload = Upload::find($upload_id);
if ($upload->deleted)
throw new Exception("This resource has been deleted.");
if ($upload->filename == '')
throw new Exception("No downloadable file found. Please email info#clouddueling.com for support.");
header("Content-Description: File Transfer");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename={$upload->uploaded_filename};");
readfile("https://s3.amazonaws.com/stackoverflow/uploads/" . $upload->filename);
exit;
} catch(Exception $e) {
return $e->getMessage();
}
}

In s3 management console window, right click and chose properties.
Click on metadata.
Click on add more metadata
Key: content-disposition
Value: attachment
Save. That's all.

Related

When i download file programmatically from s3 bucket, It gives me error It looks like we don't support this file format

When I download file from s3 bucket, I am using aws-sdk for that, it downloads the files but when i open that file it says It looks like we don't support this file format, here is my full code of it, can anyone please check my code and help me why image is doesn't open the image, my wholde code is in PHP, It looks like small error but doesn't working for me
$bucket = '*****';
$keyname = '1560346461616.jpg';
$s3 = new S3Client([
'version' => 'latest',
'region' => '******',
'credentials' => [
'key' => '******',
'secret' => '******',
],
]);
$result = $s3->getObject([
'Bucket' => $bucket,
'Key' => $keyname,
]);
header("Content-Type: {$result['ContentType']}");
header('Content-Disposition: attachment; filename='.$keyname);
echo $result['Body'];
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
Check the content type of your .jpg file stored in s3. Ensure the metadata for this object says image/jpeg.I don't think it is related to the object you downloaded,maybe the download file was corrupted.

Can't access uploaded files via Podio API

We actually want to upload a file and attach it to an item but we're having problems just uploading it.
We are having a problem uploading an image into an item. We cant seem to access the image we uploaded to Podio via the API. We get a - "Sorry, you don't have access to this file. You might want to ask your admin to provide you the access to this file."
Which is so weird because everyone in our team cant access it, and we're admins on our workspaces. I also setup the api/secret keys and i'm and admin on that workspace. Whats wrong with this?
This is the code:
Podio::setup($client_id, $client_secret);
try {
Podio::authenticate_with_app($app_id, $app_token);
$upload = PodioFile::upload('PATH_TO_FILE', 'test_image.jpg');
if( $upload != ""){
echo "<br><br>Image uploaded to podio!<br><br>";
echo "<pre>".$upload."</pre>";
echo "<br><br>".$upload->file_id."<br>";
echo $upload->link."<br>";
}
if( PodioFile::attach( $upload->file_id, array('ref_type' => 'item', 'ref_id' => 43 )) != ""){
echo "<br><br>Image attached to item!<br>";
}
}catch (PodioError $e) {
echo $e->body['error_description'];
}
Podio::set_debug(true);
You can't access file itself until it's linked to something because files don't have own access-control system. Once file is attached to item or task or workspace or whatever else, then you might be able to access it if you have enough rights :).
There is at least one error item_id=43 is for sure not your item, so you can't attach file to it.

Correct code to upload local file to S3 proxy of API Gateway

I created an API function to work with S3. I imported the template swagger. After deployment, I tested with a Node.js project by the npm module aws-api-gateway-client.
It works well with: get bucket lists, get bucket info, get one item, put a bucket, put a plain text object, however I am blocked with put a binary file.
firstly, I ensure ACL is allowed with all permissions on S3. secondly, binary support also added
image/gif
application/octet-stream
The code snippet is as below. The behaviors are:
1) after invokeAPI, the callback function is never hit, after sometime, the Node.js project did not respond. no any error message. The file size (such as an image) is very small.
2) with only two times, the uploading seemed to work, but the result file size is bigger (around 2M bigger) than the original file, so the file is corrupt.
Could you help me out? Thank you!
var filepathname = './items/';
var filename = 'image1.png';
fs.stat(filepathname+filename, function (err, stats) {
var fileSize = stats.size ;
fs.readFile(filepathname+filename,'binary',function(err,data){
var len = data.length;
console.log('file len' + len);
var pathTemplate = '/my-test-bucket/' +filename ;
var method = 'PUT';
var params = {
folder: '',
item:''
};
var additionalParams = {
headers: {
'Content-Type': 'application/octet-stream',
//'Content-Type': 'image/gif',
'Content-Length': len
}
};
var result1 = apigClient.invokeApi(params,pathTemplate,method,additionalParams,data)
.then(function(result){
//never hit :(
console.log(result);
}).catch( function(result){
//never hit :(
console.log(result);
});;
});
});
We encountered the same problem. API Gateway is meant for limited data (10MB as of now), limits shown here,
http://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html
Self Signed URL to S3:
Create an S3 self signed URL for POST from the lambda or the endpoint where you are trying to post.
How do I put object to amazon s3 using presigned url?
Now POST the image directly to S3.
Presigned POST:
Apart from posting the image if you want to post additional properties, you can post it in multi-form format as well.
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property
If you want to process the file after delivering to S3, you can create a trigger from S3 upon creation and process with your Lambda or anypoint that need to process.
Hope it helps.

Set content type in S3 when attaching via Paperclip 4?

I'm trying to attach CSV files to a Rails3 model using paperclip 4.1.1, but I'm having trouble getting the content-type as reported by S3 to be text/csv (instead I am getting text/plain). When I subsequently download the file from S3, the extension is getting changed to match the content-type instead of preserving the original extension (so test.csv is downloaded as test.txt).
From what I can see, when you upload a file, the FileAdapter will cache the content-type on creation with whatever value was determined by the ContentTypeDetector (which calls file -b --mime filename). Unfortunately, CSV files return text/plain which makes sense, as how can you really distinguish this? Attempts to set the content-type with attachment.instance_write(:content_type, 'text/csv') only set the value in the model and do not affect what gets written to S3.
FileAdapter's content_type initialized here: https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/io_adapters/file_adapter.rb#L14
Call which creates that io_adapter:
https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/attachment.rb#L98
I really have a generic upload here (so I can't hard-code the content type in the S3 headers definition in has_attached_file), and I don't really want the content-type spoofing protection. Any ideas/suggestions? I would prefer not to downgrade to 3.5 because it would mean just delaying the pain, but if that's the only way, I'll entertain it...
If you are using fog then you can do something like this:
has_attached_file :report,
fog_file: lambda { |attachment|
{
content_type: 'text/csv',
content_disposition: "attachment; filename=#{attachment.original_filename}",
}
}
If you are using Amazon S3 as your storage provider, then something like this should work:
has_attached_file :report
s3_headers: lambda { |attachment|
{
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename=#{attachment.original_filename}",
}
}
Had this problem just recently and both the post process and the lambda don't work so did a work around. Same with others observation, the values of the attachment is empty when calling the s3 lambda headers.
add this line to the model
attr_accessor :tmp_content_type, :tmp_file_name
override the file assignment method so we could get the file info and store it for later use
def file=(f)
set_tmp_values(f.path)
file.assign(f)
end
def set_tmp_values(file_path)
self.tmp_file_name = File.basename(file_path)
self.tmp_content_type = MIME::Types.type_for(file_path).first.content_type
end
Use the temp vars
:s3_headers => lambda { |attachment|
{
'Content-Type' => attachment.tmp_content_type,
"Content-Disposition" => "attachment; filename=\"# {attachment.tmp_file_name}\""
}
}

s3 file to local system php

how would I get the file from amazon s3 to local system using php.
I am trying to do this but its not working
$s3 = new AmazonS3("key 1", " acces pass");
$s3->getObject("Bucket/filename");
//write to local
$fp = fopen('/tmp/filename.mp4', 'w');
fpassthru($fp);
EDIT
I am trying to save the file to my local server from s3
As of 3.35.x verison AWS SDK -- the following snippet works with SaveAs.
Notice the buket name, key, and saveas with full path with file name.
$result = $s3->getObject(array(
'Bucket' => $bucket,
'Key' => $key,
'SaveAs' => $path . $model->file_name,
));
Check out the docs for getObject:
You need to either pass the remote file name as the 2nd param, then in the options set the value of 'fileDownload' to a file name or an OPEN file resource as a parameter there.
Example:
$s3->getObject('myBucket','myRemoteFile', array('fileDownload' => 'localFileName'));