PHP:获取文件扩展名不工作的上传到S3(PHP: Get file extension not w

2019-06-24 10:01发布

我使用的是亚马逊S3 API上传文件,我每次我上传时间更改文件的名称。

因此,例如:

Dog.png> 3Sf5f.png

现在,我得到的随机部分工作作为这样的:

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的名称参数为这样的:

$params->key = rand_string(5);

现在我的问题是,这不会显示任何扩展。 因此,该文件将上载为3Sf5f而不是3Sf5f.png

变量$文件名给了我与它的扩展名的文件的全名。

如果我使用$params->key = rand_string(5).'${filename}'; 我得到:

3Sf5fDog.png

所以我试图找回$文件扩展名,并将其应用。 我试过30种多方法,而没有任何积极的一个。

例如我尝试了$ PATH_INFO(),我试图SUBSTR(strrchr($ FILE_NAME,),1 ''); 任何更多。 所有这些给我任何3Sf5fDog.png或只是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 (有整个脚本没有其他文件)。

我是我做错了吗? 这是很无奈。

Answer 1:

变量$文件名(因此“$ {文件名}”)的范围并不在你的代码(基于原始浆糊引擎收录行号)的1053线。

所以,不管你做什么,你永远也找不到一个不存在的变量的扩展。


而我终于摸索出自己在做什么。 我想这是一个扩展的PHP:上传前重命名文件

答案很简单:因为你envisage.Why你不能做到这一点 - 在“$文件名”是不是在那个URL的创建时间分析,但变量传递到Amazon S3和处理那里。

解决方案

所以,我能想到的唯一的选择是有使用“successRedirect”参数设置为指向另一个URL。 该URL将收到“斗”,并从亚马逊的“钥匙”作为查询参数( http://doc.s3.amazonaws.com/proposals/post.html#Dealing_with_Success )。 点到重命名(复制+删除)在Amazon S3文件PHP脚本,然后将用户重定向到另一个成功画面。

所以,

在你的代码,34行,

  1. 添加一个完全合格的URL你要编写一个新的PHP脚本文件。
  2. PHP脚本西港岛线得到传递给它的桶和关键
  3. 从“钥匙”创建新的文件名
  4. 使用功能“公共静态功能copyObject($ srcBucket,$ srcUri,$桶,$ URI)”,以上传的文件复制到新名称
  5. 然后删除原始(使用DeleteObject的($斗,$ URI))
  6. 然后将用户重定向到要送他们

这将不正是你想要的。


在回答您的意见“这是唯一的出路 - 怎么样的成本,因为每个请求亚马逊收费吗?”

删除请求是免费的。 上同一个桶中移动时,没有数据传送费用(或甚至在相同的区域)。 因此,该解决方案(这是没有你传送到一个中间服务器,重命名和上载的唯一途径)双打上传一个从1C每1000个上传至每1000个上传2C成本。 这是我花10分钟@ 200 /每小时$发现并响应= $ 33 = 1666666上传! 成本苍白有点当你做数学:)

与其他解决方案比较:做一个发布到Web服务器,重命名文件,然后从网络服务器上传:您从客户为例移动所有带宽tdirectly自己 - 的两倍。 而这也带来风险和增加可能的故障点。


在回答“不行的,我给你上传一个文件,那么旧的被删除”

我会assusme你上传一个文件,然后内一两秒钟重新命名它,这不是一个问题。 但是如果你想OT出示担保的每个文件被上传,那么你需要做很多超过反正创建一个随机文件名:

  1. 有你的“最终”斗
  2. 每次上传,创建一个临时记录(这是每1000桶1C,如果你对成本担心)
  3. 上传到临时记录
  4. 创建随机名称,检查是否在最后斗不存在(每1000个会检查1C)
  5. 将文件复制到最终桶(新名称)
  6. 删除已上传的文件以及桶。
  7. 定期清理水桶所在的文件上传不完整。


Answer 2:

$fileSplit = explode('.',$filename);
$extension = '.'.$fileSplit[count($fileSplit) - 1];

此爆炸()把该文件名与周期作为分隔符的阵列,然后抓住最后一块阵列(柜面文件名是foo.bar.jpg)的,并把在它前面的周期。 这应该得到你想要的扩展,将其追加到rand_string(5)。

$params->key = rand_string(5).$extension;


Answer 3:

我认为如下简单的东西应该努力从中提取文件名的文件扩展名:

function getFileExtension($fileName)
{
    $ext = '';
    if(strpos($fileName, ".") !== false)
    {
        $ext = end(explode(".", $fileName));
    }
    return $ext;
}


Answer 4:

如果你上传图片试试这个

$dim = getimagesize($file);
$type = $dim[2];
if( $type == IMAGETYPE_JPEG ) $ext=".jpg"; 
if( $type == IMAGETYPE_GIF ) $ext=".gif"; 
if( $type == IMAGETYPE_PNG ) $ext=".png";

$params->key = rand_string(5).$ext;


Answer 5:

如果你有什么happends:

$filename = "${filename}";
echo $filename;
die();

你得到的东西像“Dog.png”? 如果不这样做有什么不对的,你所得到的文件名的方式。 如果你得到的东西像“Dog.png”,这里是我用它来获取文件扩展名。

$pieces = explode('.',trim($filename));
$extension = end($pieces);

然后,你应该能够做到这一点:

$params->key = rand_string(5).'.'.$extension;


Answer 6:

你需要先找出原来的扩展名是什么,而不是重命名整个文件。 因此,保持了扩展和重命名德文件名。

假设你已经在$ IMAGE_NAME形象的名字:

$image_name = "image.png";
$random_string = "random";

list($filename,$fileext) = explode(".",$image_name);
$new_name = $random_string.'.'.$fileext;
rename($image_name,$new_name);  


Answer 7:

确定这里是另一种尝试,我当我有麻烦在服务器端的扩展使用。 我所做的是,我用JavaScript来解压文件扩展名,并通过邮寄的发送。

<script type="text/javascript" >
function fileinfo() {
var file = document.form.file.value;
document.getElementById("ext").value = file.split('.').pop();
document.myform.submit();   
}
</script>
<form name="myform" enctype="multipart/form-data" onsubmit="fileinfo();">
<input type="file" name="file">
<input type="hidden" name="ext">
//rest of the form
</form>

在接下来的php文件就可以直接使用$ _ POST [“分机”]作为扩展名。 希望帮助。 让我知道,如果你有这个实施任何麻烦



Answer 8:

我在我的网站上使用这个(和多年工作正常):

$file = 'yourOriginalfile.png';

//get the file extension
$fileExt = substr(strrchr($file, '.'), 1);

//create a random name and add the original extension
$fileUniqueName = md5(uniqid(mktime())) . '.' . $fileExt;

rename($file,$fileUniqueName); 

你的函数生成过短文件名(5个字符),这样一来造成长文件名,避免碰撞的文件名。

示例输出:aff5a25e84311485d4eedea7e5f24a4f.png



Answer 9:

看来什么实际发生上,而不是现在完全生产的文件名,你实际上传递一个非常小的“程序”,通过该接口,因此它可以再后来产生的文件名(当变量$文件存在并且在范围)。 接口的另一侧最终执行该“节目”你传递,从而产生经修改的文件名。 (当然传递一个“计划”到别的以后执行的东西并不容易,使调试真正的轻松:-)

(这当然取决于你是否要“使这项工作”或“做不同的方式。”“不同的方法”一般包括重命名或将文件复制自己之前,你甚至尝试调用上传界面,并且被描述在其他的答案。)

如果你决定要“使工作”,那么整个文件名参数必须是一个程序,而不是只是其中的一部分。 这多少有些不常见的功能通常包括封闭在引号将整个字符串。 (你也需要做一些现有的字符串中的单引号这样他们就不会太快结束引号的字符串。一种方法是用一个反斜杠引用他们每个人。另一种方式可能看起来更干净,通常的工作原理是用双引号替换它们。)换句话说,我相信下面的代码会为你工作(我没有合适的环境来测试它,所以我不知道)。

$file_extension = 'substr(strrchr(${filename}, "."), 1)';

$params->key = rand_string(5).$file_extension;

(一旦你得到它的工作,你可能想重温你的命名方案。也许名称需要久一点。或许它应该包括一些身份信息{像今天的日期,或文件的原始名称}。您可能打类似$ file_base.rand_string(7)。$ FILE_EXTENSION。



Answer 10:

未经检验的,但很简单的工作:

$ext = pathinfo($filename, PATHINFO_EXTENSION);

将返回扩展部分(不包括“”)



Answer 11:

一个简单的方法来重新命名文件和计算扩展

$fileName = 'myRandomFile.jpg';

// separate the '.'-separated parts of the file name
$parts = explode( '.', $fileName );

// Solution will not work, if no extension is present
assert( 1 < count( $parts ) );

// keep the extension and drop the last part
$extension = $parts[ count( $parts ) - 1 ];
unset( $parts[ count( $parts ) - 1 ] );

// finally, form the new file name
$newFileName = md5( 'someSeedHere' + implode( '.', $parts )) . '.' . $extension;

echo $extension             // outputs jpg
   . ' - ' 
   . $newFileName           // outputs cfcd208495d565ef66e7dff9f98764da.jpg
   ;

注意, MD5()始终是32个字节长和非唯一的关于所述计算出的值 。 对于许多实际情况下,这是唯一够了

附录

此外,您可以使用此解决方案来跟踪变量的变化

abstract class CSTReportDelegate {

    abstract public function emitVariableChange( $variableName, $oldValue, $newValue );
    abstract public function emitVariableSetNew( $variableName, $newValue );

}

class CSTSimpleReportDelegate extends CSTReportDelegate {

    public function emitVariableChange( $variableName, $oldValue, $newValue ) {
        echo '<br />[global/change] '. $variableName . ' : ' . print_r( $oldValue, true ) . ' &rarr; ' . print_r( $newValue, true );
    }

    public function emitVariableSetNew( $variableName, $newValue ) {
        echo '<br />[global/init] '. $variableName . '   &rarr; ' . print_r( $newValue, TRUE );
    }

}


class CSysTracer {

    static protected 
        $reportDelegate;

    static private 
        $globalState = array();

    static private  
        $traceableGlobals = array();

    static private 
        $globalTraceEnabled = FALSE;

    const 
        DEFAULT_TICK_AMOUNT = 1;

    static public 
    function setReportDelegate( CSTReportDelegate $aDelegate ) {
        self::$reportDelegate = $aDelegate;
    }


    static public 
    function start( $tickAmount = self::DEFAULT_TICK_AMOUNT ) {

        register_tick_function ( array( 'CSysTracer', 'handleTick' ) );

    }


    static public 
    function stop() {

        unregister_tick_function( array( 'CSysTracer', 'handleTick' ) );

    }

    static public 
    function evalAndTrace( $someStatement ) {

        declare( ticks = 1 ); {
            self::start();
            eval( $someStatement );
            self::stop();
        }
    }

    static public 
    function addTraceableGlobal( $varName ) {

        if ( is_array( $varName )) {
            foreach( $varName as $singleName ) {
                self::addTraceableGlobal( $singleName ); 
            }
            return;
        }

        self::$traceableGlobals[ $varName ] = $varName;

    }

    static public 
    function removeTraceableGlobal( $varName ) {
        unset( self::$traceableGlobals[ $varName ] );   
    }

    /**
     * Main function called at each tick. Calls those functions, which
     * really perform the checks.
     * 
     */
    static public 
    function handleTick( ) {

        if ( TRUE === self::$globalTraceEnabled ) { 
            self::traceGlobalVariable();
        }

    }

    static public 
    function enableGlobalsTrace() {
        self::$globalTraceEnabled = TRUE;   
    }


    static public 
    function disableGlobalsTrace() {
        self::$globalTraceEnabled = FALSE;  
    }

    static public 
    function traceGlobalVariable( ) {

        foreach( self::$traceableGlobals as $aVarname ) {

            if ( ! isset( $GLOBALS[ $aVarname ] )) {
                continue;
            }

            if ( ! isset( self::$globalState[ $aVarname ] ) ) {

                self::$reportDelegate->emitVariableSetNew( $aVarname, $GLOBALS[ $aVarname ] );
                self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ];
                continue;
            }

           if ( self::$globalState[ $aVarname ] !== $GLOBALS[ $aVarname ]) {

             self::$reportDelegate->emitVariableChange( $aVarname, self::$globalState[ $aVarname ], $GLOBALS[ $aVarname ] );

           }

           self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ];

        }

    }

}

的样品用例:

ini_set("display_errors", TRUE);
error_reporting(E_ALL);

require_once( dirname( __FILE__ ) . '/CStatementTracer.inc.php' );

/* Ticks make it easy to have a function called for every line of PHP
 *  code. We can use this to track the state of a variable throughout
 * the execution of a script.
 */



CSysTracer::addTraceableGlobal( array( 'foo', 'bar' ));

CSysTracer::setReportDelegate( new CSTSimpleReportDelegate() ); 
CSysTracer::enableGlobalsTrace();

CSysTracer::start(); 
declare( ticks = 1 );

   //
   // At this point, tracing is enabled. 
   // Add your code or call your functions/methods here
   //

CSysTracer::stop();


Answer 12:

这个怎么样?

$temp = rand_string(5).'${filename}';         //should be 3Sf5fDog.png
$ext = pathinfo($temp, PATHINFO_EXTENSION); //should be .png
$temp2 = rand_string(5) . $ext;             //should be 4D47a.png


文章来源: PHP: Get file extension not working on uploads to S3