PHP:获取文件扩展名不适用于上传到 S3
我正在使用 Amazon S3 API 上传文件,并且每次上传时我都会更改文件名.
I am using the Amazon S3 API to upload files and I am changing the name of the file each time I upload.
例如:
狗.png > 3Sf5f.png
Dog.png > 3Sf5f.png
现在我得到了这样的随机部分:
Now I got the random part working as such:
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
所以我将 random_string 设置为 name 参数:
So I set the random_string to the name parameter as such:
$params->key = rand_string(5);
现在我的问题是这不会显示任何扩展名.因此文件将上传为 3Sf5f
而不是 3Sf5f.png
.
Now my problem is that this wont show any extension. So the file will upload as 3Sf5f
instead of 3Sf5f.png
.
变量 $filename 给出了文件的全名及其扩展名.
The variable $filename gives me the full name of the file with its extension.
如果我使用 $params->key = rand_string(5).'${filename}';
我得到:
If I use $params->key = rand_string(5).'${filename}';
I get:
3Sf5fDog.png
所以我尝试检索 $filename 扩展名并应用它.试了30多种方法都没有一个肯定的.
So I tried to retrieve the $filename extension and apply it. I tried more than 30 methods without any positive one.
例如我尝试了 $path_info(),我尝试了 substr(strrchr($file_name,'.'),1);还有更多.他们都给我 3Sf5fDog.png
或只是 3Sf5f
.
For example I tried the $path_info(), I tried substr(strrchr($file_name,'.'),1); any many more. All of them give me either 3Sf5fDog.png
or just 3Sf5f
.
我尝试过的示例:
// As @jcinacio pointed out. Change this to:
//
// $file_name = "${filename}";
//
$file_name = '${filename}' // Is is wrong, since '..' does not evaluate
$params->key = rand_string(5).$file_name;
=
3Sf5fDog.png
.
$file_name = substr(strrchr('${filename}', '.'), 1);
$params->key = rand_string(5).$file_name;
=
3Sf5f
.
$filename = "example.png" // If I declare my own the filename it works.
$file_name = substr(strrchr('${filename}', '.'), 1);
$params->key = rand_string(5).$file_name;
=
3Sf5f.png
整个类文件:http://pastebin.com/QAwJphmW(整个脚本没有其他文件).
The entire class file: http://pastebin.com/QAwJphmW (there are no other files for the entire script).
我做错了什么?这真的很令人沮丧.
变量 $filename(因此${filename}")不在代码第 1053 行的范围内(行编号基于 pastebin 的原始粘贴).
The variable $filename (and thus "${filename}") is NOT IN SCOPE at line 1053 of your code (line numbering based on raw paste from pastebin).
所以,无论你做什么,你都找不到不存在的变量的扩展名.
So, no matter what you do, you'll never find the extension of a variable that does not exist.
我终于弄清楚你在做什么了.我认为这是 PHP:上传前重命名文件
And I've finally worked out what you're doing. I presume this is an extension of PHP: Rename file before upload
简单的答案:你不能像你想象的那样做.为什么 - 在创建 URL 时没有解析$filename",但变量被传递到 Amazon S3 并在那里处理.
Simple answer: you can't do it as you envisage.Why - the '$filename' is not parsed at the time that URL is created, but the variable is passed to Amazon S3 and handled there.
解决办法
因此,我能想到的唯一选择是使用successRedirect"参数指向另一个 URL.该 URL 将从亚马逊接收bucket"和key"作为查询参数(http://doc.s3.amazonaws.com/proposals/post.html#Dealing_with_Success).将其指向一个 PHP 脚本,该脚本重命名 Amazon S3 上的文件(复制 + 删除),然后将用户重定向到另一个成功屏幕.
So, the only option I can think of is to have use the "successRedirect" parameter to point to another URL. That URL will receive the "bucket" and "key" as query parameters from Amazon (http://doc.s3.amazonaws.com/proposals/post.html#Dealing_with_Success). Point that to a PHP script that renames the file on Amazon S3 (copy + delete), then redirects the user to another success screen.
所以,
在您的代码中,第 34 行,
in your code, line 34,
- 将完全限定的 URL 添加到您要访问的新 php 脚本文件中写.
- php 脚本将获取传递给它的存储桶和密钥
- 从密钥"创建新文件名
- 使用函数公共静态函数copyObject($srcBucket, $srcUri, $bucket, $uri)" 复制上传的文件改为新名称
- 然后删除原来的(使用deleteObject($bucket, $uri))
- 然后将用户重定向到您要发送的位置
这将完全符合您的要求.
That will do exactly what you want.
回应您的评论这是唯一的方法吗?亚马逊按请求收取的费用如何?"
In response to your comments "Is this the only way - what about the costs as Amazon charge per request?"
删除请求是免费的.在同一个存储桶(甚至在同一个区域)上移动时没有数据传输成本.因此,此解决方案(这是您无需转移到中间服务器、重命名和上传的唯一方法)它将上传成本从每 1000 次上传 1c 增加到每 1000 次上传 2c.我花了 10 分钟 @ 200 美元/小时才发现并回复 = 33 美元 = 1,666,666 次上传!当你做数学时,成本会变得苍白一些:)
Delete requests are free. No data transfer costs when moving on the same bucket (or even in the same region). So this solution (which is the only way without you transferring to an intermediate server, renaming and uploading) it doubles the cost of upload a from 1c per 1000 uploads to 2c per 1000 uploads. It's taken me 10 minutes @ $200/hour to find that out and respond = $33 = 1,666,666 uploads! Costs pale a bit when you do the maths :)
与其他解决方案相比:向网络服务器发布帖子,重命名文件,然后从网络服务器上传:您将所有带宽从 clinet tdirectly 转移到您自己 - 两次.这也会带来风险并增加可能的故障点.
Compare with the other solution: do a post to an webserver, rename the file and then upload from the webserver: you move all the bandwidth from the clinet tdirectly to yourself - twice. And this also introduces risk and increased possible failure points.
响应不起作用.我上传文件然后旧文件被删除"
In response to "Doesn't work. I you upload a file then the old one gets deleted"
我认为这不是问题,因为您上传文件然后在一两秒钟内重命名它.但是如果你想保证每个文件都被上传,那么你需要做的不仅仅是创建一个随机文件名:
I would assusme this is not a problem as you upload a file and then rename it within a second or two. But if you want ot gurantee each file gets uploaded, then you need to do a lot more than create a random filename anyway:
- 拥有你的最终"存储桶
- 为每次上传创建一个临时存储桶(如果您担心成本,则为每 1000 个存储桶 1c)
- 上传到临时存储桶
- 创建随机名称,检查最终存储桶中是否不存在(每 1000 次检查 1c)
- 将文件复制到最终存储桶(使用新名称)
- 删除上传的文件以及存储桶.
- 定期清理文件上传未完成的存储桶.