花了好幾個小時追蹤一個 copy() 錯誤:權限被拒絕(並適當地擔心在 winXP 上的 chmod),值得指出的是,「目標」需要包含實際的檔案名稱!--- 不僅僅是您想要複製到的資料夾的路徑.......
真是的!
希望這可以為其他人節省數小時徒勞的除錯時間
(PHP 4, PHP 5, PHP 7, PHP 8)
copy — 複製檔案
from
來源檔案的路徑。
to
目標路徑。如果 to
是一個 URL,當 wrapper 不支援覆寫現有檔案時,複製操作可能會失敗。
如果目標檔案已經存在,它將會被覆寫。
context
使用 stream_context_create() 建立的有效上下文資源。
範例 #1 copy() 範例
<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';
if (!copy($file, $newfile)) {
echo "複製 $file 失敗...\n";
}
?>
花了好幾個小時追蹤一個 copy() 錯誤:權限被拒絕(並適當地擔心在 winXP 上的 chmod),值得指出的是,「目標」需要包含實際的檔案名稱!--- 不僅僅是您想要複製到的資料夾的路徑.......
真是的!
希望這可以為其他人節省數小時徒勞的除錯時間
我花了很多時間才找出 copy() 出錯的問題所在。它「不會」建立任何目錄。它只會複製到現有的路徑。所以在複製前請先建立目錄。希望我能幫上忙。
別忘了;您可以對遠端檔案使用 copy,而不是使用繁瑣的 fopen 方法。例如:
<?php
if(!@copy('http://someserver.com/somefile.zip','./somefile.zip'))
{
$errors= error_get_last();
echo "COPY ERROR: ".$errors['type'];
echo "<br />\n".$errors['message'];
} else {
echo "File copied from remote!";
}
?>
這是一個我用來移除和複製非空目錄的簡單腳本。當您不確定檔案類型時,這非常有用。
我使用這些來管理我的網站插件的資料夾和 zip 壓縮檔。
<?php
// 移除檔案和非空目錄
function rrmdir($dir) {
if (is_dir($dir)) {
$files = scandir($dir);
foreach ($files as $file)
if ($file != "." && $file != "..") rrmdir("$dir/$file");
rmdir($dir);
}
else if (file_exists($dir)) unlink($dir);
}
// 複製檔案和非空目錄
function rcopy($src, $dst) {
if (file_exists($dst)) rrmdir($dst);
if (is_dir($src)) {
mkdir($dst);
$files = scandir($src);
foreach ($files as $file)
if ($file != "." && $file != "..") rcopy("$src/$file", "$dst/$file");
}
else if (file_exists($src)) copy($src, $dst);
}
?>
敬上!
如果您需要先確定資料夾存在,這是一個簡單的小技巧
<?php
$srcfile='C:\File\Whatever\Path\Joe.txt';
$dstfile='G:\Shared\Reports\Joe.txt';
mkdir(dirname($dstfile), 0777, true);
copy($srcfile, $dstfile);
?>
就這麼簡單。
在 Windows 上,php-7.4.19-Win32-vc15-x64 - copy() 損壞了一個 6GB 的 zip 檔案。我們唯一的 recours是寫
function file_win_copy( $src, $dst ) {
shell_exec( 'COPY "'.$src.'" "'.$dst.'"');
return file_exists($dest);
}
以下是一個程式碼片段,用於將檔案從網路伺服器下載到本機檔案。
它示範了請求的有用客製化(例如設定 User-Agent 和 Referrer,網站通常需要這些),以及如何僅在網站上的副本比本機副本更新時才下載檔案。
它進一步示範了如何處理回應標頭(如果伺服器設定)以確定時間戳記和檔案名稱。會檢查檔案類型,因為某些伺服器會返回 200 OK 返回碼和文字「找不到」頁面,而不是正確的 404 返回碼。
<?php
// $fURI: URL to a file located on a web server
// $target_file: Path to a local file
if ( file_exists( $target_file ) ) {
$ifmodhdr = 'If-Modified-Since: '.date( "r", filemtime( $target_file ) )."\r\n";
}
else {
$ifmodhdr = '';
}
// set request header for GET with referrer for modified files, that follows redirects
$arrRequestHeaders = array(
'http'=>array(
'method' =>'GET',
'protocol_version' =>1.1,
'follow_location' =>1,
'header'=> "User-Agent: Anamera-Feed/1.0\r\n" .
"Referer: $source\r\n" .
$ifmodhdr
)
);
$rc = copy( $fURI, $target_file, stream_context_create($arrRequestHeaders) );
// HTTP request completed, preserve system error, if any
if( $rc ) {
if ( fclose( $rc ) ) {
unset( $err );
}
else {
$err = error_get_last();
}
}
else {
$err = error_get_last();
}
// Parse HTTP Response Headers for HTTP Status, as well filename, type, date information
// Need to start from rear, to get last set of headers after possible sets of redirection headers
if ( $http_response_header ) {
for ( $i = sizeof($http_response_header) - 1; $i >= 0; $i-- ) {
if ( preg_match('@^http/\S+ (\S{3,}) (.+)$@i', $http_response_header[$i], $http_status) > 0 ) {
// HTTP Status header means we have reached beginning of response headers for last request
break;
}
elseif ( preg_match('@^(\S+):\s*(.+)\s*$@', $http_response_header[$i], $arrHeader) > 0 ) {
switch ( $arrHeader[1] ) {
case 'Last-Modified':
if ( !isset($http_content_modtime) ) {
$http_content_modtime = strtotime( $arrHeader[2] );
}
break;
case 'Content-Type':
if ( !isset($http_content_image_type) ) {
if ( preg_match('@^image/(\w+)@ims', $arrHeader[2], $arrTokens) > 0 ) {
if ( in_array(strtolower($arrTokens[1]), $arrValidTypes)) {
$http_content_image_type = $arrTokens[1];
break;
}
}
throw new Exception( "Error accessing file $fURI; invalid content type: $arrHeader[2]", 2);
}
break;
case 'Content-Disposition':
if ( !isset($http_content_filename) && preg_match('@filename\\s*=\\s*(?|"([^"]+)"|([\\S]+));?@ims', $arrHeader[2], $arrTokens) > 0 ) {
$http_content_filename = basename($arrTokens[1]);
}
break;
}
}
}
}
if ( $http_status ) {
// Make sure we have good HTTP Status
switch ( $http_status[1] ) {
case '200':
// SUCCESS: HTTP Status is "200 OK"
break;
case '304':
throw new Exception( "Remote file not newer: $fURI", $http_status[1] );
break;
case '404':
throw new Exception( "Remote file not found: $fURI", $http_status[1] );
break;
default:
throw new Exception( "HTTP Error, $http_status[2], accessing $fURI", $http_status[1] );
break;
}
}
elseif ( $err ) {
// Protocol / Communication error
throw new Exception( $err['message']/*."; Remote file: $fURI"*/, $err['type'] );
}
else {
// No HTTP status and no error
throw new customException( "Unknown HTTP response accessing $fURI: $http_response_header[0]", -1 );
}
?>
注意事項
1. 目前 copy() 並未正確處理 304 回應碼。它不會執行複製(可能設定 RC),而是會用零長度檔案覆寫目標檔案。
2. 使用 HTTP 1.1 協定時,存取遠端檔案清單可能會有問題。如果您遇到逾時錯誤,請嘗試使用預設的 1.0 協定版本。
在 Windows 8.1 下,從一個 NTFS 檔案系統複製大型檔案到另一個 NTFS 檔案系統,只會複製前 4 GiB,其餘檔案會被忽略。
因此,如果您認為檔案大於 4 GiB,不要執行
copy($source,$destination);
最好執行以下操作
exec("xcopy $source $destination");
我會檢查這個問題在 Linux 下是否也有效。
這取決於 PHP 是否以 64 位元模式編譯?
這是一個簡單的遞迴函數,用於複製整個目錄
請注意,要自行檢查以確保您第一次呼叫它的目錄存在。
<?php
function recurse_copy($src,$dst) {
$dir = opendir($src);
@mkdir($dst);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
recurse_copy($src . '/' . $file,$dst . '/' . $file);
}
else {
copy($src . '/' . $file,$dst . '/' . $file);
}
}
}
closedir($dir);
}
?>
有些主機基於安全性考量停用了 copy() 函式
而對於某些情況,複製功能很重要,所以這是一個簡單的函式,可以達到與 copy 函式相同的效果
PHP 真是太好用了,我喜歡 PHP
<?php
function copyemz($file1,$file2){
$contentx =@file_get_contents($file1);
$openedfile = fopen($file2, "w");
fwrite($openedfile, $contentx);
fclose($openedfile);
if ($contentx === FALSE) {
$status=false;
}else $status=true;
return $status;
}
?>
複製檔案並保留檔案時間戳記
<?php
if (copy($from, $to))
touch($to, filemtime($from), fileatime($from));
?>