PHP文件那些事儿

0、参考资料

1、PHP上传文件

PHP后台获取上传文件,利用全局变量$_FILES获取上传文件。

$schemaTmpFile = $_FILES['owndata_schema'];
# 文件属性
array(5) {
  'name' =>
  string(12) "desc-foo.csv"
  'type' =>
  string(24) "application/vnd.ms-excel"
  'tmp_name' =>
  string(19) "/data/tmp/php8zDKJi"
  'error' =>
  int(0)
  'size' =>
  int(180)
}

文件属性:

  • 1、 name: 下标指的是上传文件的文件名。
  • 2、**type:下标指的是上传文件的类型。 **
  • 3、 **tmp_name: 下标指的是上传的文件在服务器端存放的临时文件名。 **
  • 4、**error: 下标是上传文件错误的表示,可用于检测文件是否上传,以便找到错误的原因。 **
  • 5、**size: 下标是上传文件的大小,单位是字节。 **

2、PHP拉取远程文件

如果文件是远程文件,首先需要判断远程文件是否真的存在。

① 判断远程文件是否存在

curl经过验证是最为靠谱的方法。

    /**
     * 判断远程文件是否存在
     * @param $remoteFile
     * @return bool
     */
    public function remoteFileExists($remoteFile)
    {
        $curl = curl_init($remoteFile);
        
// CURLOPT_NOBODY设置为true,因为不需要真正的读取文件内容,只需要判断是否存在
        curl_setopt($curl, CURLOPT_NOBODY, true);
        $result = curl_exec($curl);
        
        $ret = false;
        
        //if request did not fail
        if ($result !== false) {
            //if request was ok, check response code
            $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            if ($statusCode == 200) {
                $ret = true;
            }
        }
        
        curl_close($curl);
        return $ret;
    }

② 获取远程文件大小

    /**
     * 获取远程文件大小
     * @param $remoteFile
     * @return mixed
     */
    public static function getRemoteFileSize($remoteFile)
    {
        $headerInfo = get_headers($remoteFile,true);
        return $headerInfo['Content-Length'];
    }

get_headers(): 返回一个数组,包含有服务器响应一个 HTTP 请求所发送的标头。可以从头部信息的Content-Length字段获取文件大小。
demo示例如下:

$remoteFile = "http://km.oa.com/files/photos/pictures/201801/1516586415_55_w157_h211.jpg";
$headerInfo = get_headers($remoteFile,true);
var_dump($headerInfo);
// 打印结果如下:
array(11) {
  [0] =>
  string(15) "HTTP/1.1 200 OK"
  'Server' =>
  string(12) "nginx/1.10.1"
  'Date' =>
  string(29) "Wed, 24 Jan 2018 09:04:03 GMT"
  'Content-Type' =>
  string(10) "image/jpeg"
  'Content-Length' =>
  string(5) "15893"
  'Last-Modified' =>
  string(29) "Mon, 22 Jan 2018 02:00:14 GMT"
  'Connection' =>
  string(5) "close"
  'ETag' =>
  string(15) ""5a6545ae-3e15""
  'Expires' =>
  string(29) "Fri, 23 Feb 2018 09:04:03 GMT"
  'Cache-Control' =>
  string(15) "max-age=2592000"
  'Accept-Ranges' =>
  string(5) "bytes"
}

3、下载远程文件

下载远程文件思路:

  • 1、获取文件内容,然后写到服务器本地地址。
  • 2、大文件,需要分片读取。
    /**
     * 下载文件&存储文件到磁盘
     * @param string $fileUrl
     * @return bool|string
     */
    protected function downFile($fileUrl = '')
    {
        $time = time();
        $taskDir = FILE_UPLOAD_BASE_PATH . '/owndata_schema';
    
        if (!is_dir($taskDir)) {
            if (mkdir($taskDir)) {
                Log::info("create dir succ:" . $taskDir);
            } else {
                Log::info("create dir fail:" . $taskDir);
                $this->err_msg = "文件路径创建失败";
                return false;
            }
        }
        
        $pathParts = pathinfo($fileUrl);
        $fileName = $pathParts['basename'];
        $fileName = $time . '_' . $fileName;
        $saveFileUrl = $taskDir . '/' .$fileName;
        // 下面核心代码
	    // fopen()可以读入大文件,每次可以指定读取一部分的内容。在操作大文件的时候也很有用。
        $rfp = fopen($fileUrl, "rb");
        $wfp = fopen($saveFileUrl, "a+");
        while (!feof($rfp)) {
            $tmpContent = fread($rfp, 1024*8);
            fwrite($wfp, $tmpContent);
        }
        fclose($rfp);
        fclose($wfp);
        
        // 返回磁盘临时存储文件路径
        return $saveFileUrl;
    }

总结:利用PHP下载文件时,应该要注重场景。如果本身只是几个小文件被下载,那么使用PHP下载比较好;但是如果PHP要承受大量下载请求,这时下载文件就不该交给PHP做,应该采取异步方式进行下载。

4、文件编码

获取上传文件或者远程文件时,有个时候需要对文件的编码进行处理。

① 获取文件编码函数

mb_detect_encoding()

② 针对UTF-8文件,去掉文件BOM头

    /**
     * UTF8 去掉文本中的 bom头
     * @param $contents
     * @return mixed
     */
    private function clearBom($contents)
    {
        $bom = chr(239) . chr(187) . chr(191);
        return str_replace($bom, '', $contents);
    }
    
    /**
     * 文件编码格式处理
     * @param $fileUrl
     */
    private function clearFileBom($fileUrl)
    {
        $encodeList = ['GBK', 'UTF-8'];
        $contents = file_get_contents($fileUrl);
        $encode = mb_detect_encoding($contents, $encodeList);
        if ($encode == 'UTF-8') {
            $contents = $this->clearBom($contents);
            file_put_contents($fileUrl, $contents);
        } else {
            $contents = StringUtil::gbkToutf8($contents);
            file_put_contents($fileUrl, $contents);
        }
    }
posted @ 2018-01-24 18:43  jaspersong  阅读(206)  评论(0编辑  收藏  举报