AWS S3 display file inline instead of force download

For some reason files in my S3 bucket are being forced as downloads instead of displaying in-line so if I copy an image link and paste it into address bar and then navigate to it, it will promote my browser to download it. Instead I actually have to click on open image to go to the url.

Any ways to change the way files are served from S3

89584 次浏览

You need to change the Content-Type. From the S3 console, right click on the object and select Properties then it's under Metadata. You can also do it programmatically: http://docs.amazonwebservices.com/AWSSDKforPHP/latest/index.html#m=AmazonS3/change_content_type

$client->putObject(array(
'Bucket'     => 'buckname',
'Key'        => $destination,
'SourceFile' => $source,
'ContentType' =>'image/jpeg', //<-- this is what you need!
'ACL'          => 'public-read'//<-- this makes it public so people can see it
));

您还需要为内联附件指定 ContentDisposition。

$client->putObject(array(
'Bucket'     => 'buckname',
'Key'        => $destination,
'SourceFile' => $source,
'ContentType' =>'image/jpeg', //<-- this is what you need!
'ContentDisposition' => 'inline; filename=filename.jpg', //<-- and this !
'ACL'          => 'public-read'//<-- this makes it public so people can see it
));

如果使用 python,可以设置 ContentType 如下所示

s3 = boto3.client('s3')


mimetype = 'image/jpeg' # you can programmatically get mimetype using the `mimetypes` module
s3.upload_file(
Filename=local_path,
Bucket=bucket,
Key=remote_path,
ExtraArgs={
"ContentType": mimetype
}
)

您也可以在 awscli 中实现同样的功能

aws s3 cp \
--exclude "*" \
--include "*.jpeg" \
--content-type="image/jpeg"  \
--metadata-directive="REPLACE" \
--recursive \
--dryrun \
s3://<bucket>/<path>/ \
s3://<bucket>/<path>/

或者,如果您希望一次修改一个对象,您可能希望使用 S3api copy-object

aws s3api copy-object \
--content-type="image/jpeg" \
--metadata-directive="REPLACE" \
--copy-source "<bucket>/<key>" \
--bucket "<bucket>" \
--key "<key>" \
--acl public-read

你可以试试这个,如果你已经在浏览器上打开了任何 URL,那么在浏览器中打开 ContentType 是强制性的,然后匿名尝试。

var params = {
Bucket: config.BUCKET_NAME,
Key: fileName,
ContentEncoding: 'base64',
ContentDisposition: 'inline',
ContentType: 'image/jpeg',
Body: buf
};

如果使用 JavaSDK 的人正在为此寻找解决方案,则需要将内容类型设置为 ObjectMetaData。

ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("image/png");


s3client.putObject(new PutObjectRequest
(bucketName, fileName + ".png", inputStream,
objectMetadata).withCannedAcl(CannedAccessControlList.PublicRead));

你可以试试这个,我喜欢。

const params = {
Bucket: 'bucket-name',
Body: file,
ACL: 'public-read',
ContentType: contentType,
ContentEncoding: 'base64',
ContentDisposition: 'attachment',
};

您也可以从 AWS S3控制台更改内容类型。

enter image description here

然后你会看到一边弹出,使用它来改变手动。

enter image description here

我发现如果我们向 ContentType传递一个空值,它将打开文件而不是下载。

当上传各种扩展名的文件时,这实际上是很好的。

$s3->putObject(
[
'Bucket' => ..,
'Key' => ..,
'Body' => ..,
'ContentType' => '', <---
'ACL' => 'public-read',
]);

如果你匿名打开它,它将工作以外,它将不会工作的某些原因。

我今天也遇到了同样的问题。问题在于在 s3中保存文件时的 Content-type属性。例如,我使用的是 Spring Boot,s3中的内容数据将 application/octet-stream保存在值属性中而不是 image/jpeg中。因此,当我打开文件链接时,浏览器下载了该文件。

这个问题的解决方案是在 s3中保存文件之前更改 Content-type

使用这两个属性强制浏览器从 s3内联文件:

「回应内容类型」及「回应内容处理」

在生成签名 URL 时,可以在 getCommand 中使用它们

$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => $bucket_name,
'Key' => $filename,
'ResponseContentType' =>  get_mime_type($filename),
'ResponseContentDisposition' => 'inline; filename='.$user_filename
]);
   

Get _ mime _ type 只是我用文件名返回 mime 类型的自定义函数

这是我在面对同样问题时使用的方法,我的 s3 bucket 中有数百万个文件,我无法在控制台中单独更改 mime 类型

真正对我有效的是在保存 S3文件之前将 ContentType参数设置为 image/png

经过两天的战斗,这就是我想要的代码。
Here is the code for anyone who uses "generate_presigned_post" in python

s3 = boto3.client('s3',
aws_access_key_id="<aws_access_key_id>",
aws_secret_access_key="<aws_secret_access_key>",
config=Config(
region_name="<region_name>",
signature_version="<signature_version>"
))


key = 'bbb.png'


creds = s3.generate_presigned_post(
Bucket="<Bucket>",
Key=key,
Fields={"Content-Type": "image/png"},
Conditions=[{"Content-Type": "image/png"}],
ExpiresIn=3600)