简体   繁体   English

我用PHP制作了一个上传脚本。 如何避免覆盖文件?

[英]I made an upload script in PHP. How do I avoid overwriting files?

I've made an image upload script using the move_uploaded_file function. 我使用move_uploaded_file函数制作了一个图像上传脚本。 This function seems to overwrite any preexisting file with the new one. 此函数似乎用新的文件覆盖任何预先存在的文件。 So, I need to check if the target location already has a file. 所以,我需要检查目标位置是否已有文件。 If it does then I need to append something to the filename(before the extension so that the file name is still valid) so the filename is unique. 如果是,那么我需要在文件名后附加一些内容(在扩展名之前,以便文件名仍然有效),因此文件名是唯一的。 I'd like to have the change be minimal instead of something like appending the datetime, if possible. 如果可能的话,我希望将更改设置为最小化而不是附加日期时间。

How can I do this with PHP? 我怎么能用PHP做到这一点?

When uploading files I will nearly always rename them. 上传文件时,我几乎总是会重命名它们。 Typically there will be some kind of database record for that file. 通常会有该文件的某种数据库记录。 I use the ID of that to guarantee uniqueness of the file. 我使用它的ID来保证文件的唯一性。 Sometimes I'll even store what the client's original filename was in the database too but I'll never keep it or the temporary name because there is no guarantee that information is good, that your OS will support it or that it's unique (which is your issue). 有时我甚至会存储客户端原始文件名在数据库中的内容,但我永远不会保留它或临时名称,因为无法保证信息良好,您的操作系统将支持它或它是唯一的(这是你的问题)。

So just rename it to some scheme of your own devising. 所以只需将其重命名为您自己设计的一些方案。 That's my advice. 这是我的建议。

If you don't have any database reference, then you could use file_exists() for this but there's no guarantee that between the time of checking if something exists and moving it that something else won't use that same filename that you'll then overwrite. 如果您没有任何数据库引用,那么您可以使用file_exists() ,但不能保证在检查某些内容是否存在之间以及移动它之前其他内容不会使用相同的文件名。覆盖。 This is a classic race condition . 这是一个经典的比赛条件

Let's assume you are submitting a file from a form where you have an input named incomingfile like this: 假设您从一个表单中提交一个文件,其中您有一个名为incomingfile如下所示:

<input type="file" id="incomingfile" name="incomingfile" />

First of all I use to "depure" the filename and copy it from the default temporary directory to a temporary directory. 首先,我使用“删除”文件名并将其从默认临时目录复制到临时目录。 This is necessary to deal with special characters. 这是处理特殊字符所必需的。 I had troubles when I didn't adopt this practice. 当我没有采用这种做法时,我遇到了麻烦。

$new_depured_filename = strtolower(preg_replace('/[^a-zA-Z0-9_ -.]/s', '_', $_FILES["incomingfile"]["name"]));
copy($_FILES["incomingfile"]["tmp_name"], 'my_temp_directory/'.$new_depured_filename);

With the following piece of code I check if the file exists, if so, I find a new name and finally copy it. 使用下面的代码我检查文件是否存在,如果是,我找到一个新名称并最终复制它。 For example if I want to write a file called myimage.jpg and it already exists I rename the pending file to myimage__000.jpg . 例如,如果我想写一个名为myimage.jpg的文件并且它已经存在,我将挂起的文件重命名为myimage__000.jpg If this exists as well I rename the pending file to myimage__001.jpg and so on until I find a non-existing filename. 如果这也存在,我将挂起的文件重命名为myimage__001.jpg,依此类推,直到找到一个不存在的文件名。

$i=0; // A counter for the tail to append to the filename
$new_filename = $new_depured_filename;
$new_filepath='myfiles/music/'.$new_filename;
while(file_exists($new_filepath)) {
    $tail = str_pad((string) $i, 3, "0", STR_PAD_LEFT); // Converts the integer in $i to a     string of 3 characters with left zero fill.
    $fileinfos = pathinfo($new_filepath); // Gathers some infos about the file
    if($i>0) { // If we aren't at the first while cycle (where you have the filename without any added strings) then delete the tail (like "__000") from the filename to add another one later (otherwise you'd have filenames like myfile__000__001__002__003.jpg)
        $previous_tail = str_pad((string) $i-1, 3, "0", STR_PAD_LEFT);
        $new_filename = str_replace('__'.$previous_tail,"",$new_filename);
    }
    $new_filename = str_replace('.'.$fileinfos['extension'],"",$new_filename); // Deletes the extension
    $new_filename = $new_filename.'__'.$tail.'.'.$fileinfos['extension']; // Append our tail and the extension
    $new_filepath = 'myfiles/music/'.$new_filename; // Crea il nuovo percorso
    $i++;
}

copy('my_temp_directory/'.$new_depured_filename, $new_filepath); // Finally we copy the file to its destination directory

unlink('my_temp_directory/'.$new_depured_filename); // and delete the temporary one

Used functions: 使用功能:
strtolower 用strtolower
preg_replace 的preg_replace
copy 复制
file_exists 文件已存在
str_pad str_pad
pathinfo PATHINFO
str_replace str_replace函数
unlink 取消链接

Don't use file_exists() for the reason that it returns true (on *nix systems at least, since directories are specialized files) if the value is a directory. 不要使用file_exists(),因为它返回true(至少在* nix系统上,因为目录是专用文件),如果值是目录。 Use is_file() instead. 请改用is_file()。

For example, say something fails and you have a string like: 例如,说某些内容失败,你有一个字符串,如:

$path = "/path/to/file/" . $file; // Assuming $file is an empty value, if something failed for example
if ( true === file_exists($path) ) { echo "This returns true"; }
if ( true === is_file($path) ) { echo "You will not read this"; }

It's caused a few problems in the past for me, so I always use is_file() rather than file_exists(). 它在过去给我带来了一些问题,所以我总是使用is_file()而不是file_exists()。

我使用日期和时间函数根据上传时间生成随机文件名。

To check if a file exists, you can use the file_exists function. 要检查文件是否存在,可以使用file_exists函数。

To cut the filename, you can use the pathinfo function. 要剪切文件名,可以使用pathinfo函数。

我用

$file_name = time() . "_" . $uploaded_file_name;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何防止PHP上传脚本覆盖现有文件? - How to prevent a PHP upload script from overwriting existing files? PHP中的SOAP。 我如何获得退货? - SOAP in PHP. How do I get a return? SOAP和PHP。 如何获取此回复? - SOAP and PHP. How do I retrieve this response? 如何在 Php 中用星星书写三角形。 (*) 我想用 while - How to write triangle with stars in Php. (*) I want to do it with while 我编写了代码以在 PHP 中上传图像。 但我得到如下错误。 现在我该怎么做才能解决这个问题? - I wrote codes to upload image in PHP. But I got the error as below. Now what should I do to solve this? 如何使用php脚本将视频和图像上传到服务器 - how do i upload a video and image to my server with php script 如何上传,插入数据库并重命名PHP中的文件? - How do i upload, insert to database and rename files in php? 如何使用php根据文件格式上传文件 - how do i upload files based on their format using php 我需要用 PHP 从我的网站发送电子邮件。 我怎样才能做到这一点? - I need to send email from my website in PHP. How can I do this? 我如何使用 php 将 3 个表中的信息显示到 1 个表中。 我正在使用 mysql 工作台 - how do i display information from 3 tables into 1 table with php. i'm using mysql workbench
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM