精细上传器实现 [英] fine-uploader implementation

查看:42
本文介绍了精细上传器实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我的HTML文件:

<html>
  <head>
    <meta charset="utf-8">
    <title>Fine Uploader Demo</title>
    <link href="fineuploader-3.4.1.css" rel="stylesheet">
  </head>
  <body>
    <div id="fine-uploader"></div>
   <script src="jquery-1.7.2.min.js"></script>
    <script src="jquery.fineuploader-3.4.1.js"></script>
    <script>

      function createUploader() {
       var uploader = new qq.FineUploader({
          // Pass the HTML element here
         element: document.getElementById('fine-uploader'),
          // or, if using jQuery
          // element: $('#fine-uploader')[0],
          // Use the relevant server script url here
          // if it's different from the default "/server/upload"
         request: {
            endpoint: 'qqFileUploader'
          }
        });
      }

      window.onload = createUploader;
    </script>
  </body>
</html>

我的PHP代码qqFileUploader.php

My PHP Code qqFileUploader.php

<?php

class qqFileUploader {

    public $allowedExtensions = array();
    public $sizeLimit = null;
    public $inputName = 'qqfile';
    public $chunksFolder = 'chunks';

    public $chunksCleanupProbability = 0.001; // Once in 1000 requests on avg
    public $chunksExpireIn = 604800; // One week

    protected $uploadName;

    function __construct(){
        $this->sizeLimit = $this->toBytes(ini_get('upload_max_filesize'));
    }

    /**
     * Get the original filename
     */
    public function getName(){
        if (isset($_REQUEST['qqfilename']))
            return $_REQUEST['qqfilename'];

        if (isset($_FILES[$this->inputName]))
            return $_FILES[$this->inputName]['name'];
    }

    /**
     * Get the name of the uploaded file
     */
    public function getUploadName(){
        return $this->uploadName;
    }

    /**
     * Process the upload.
     * @param string $uploadDirectory Target directory.
     * @param string $name Overwrites the name of the file.
     */
    public function handleUpload($uploadDirectory, $name = null){

        if (is_writable($this->chunksFolder) &&
            1 == mt_rand(1, 1/$this->chunksCleanupProbability)){

            // Run garbage collection
            $this->cleanupChunks();
        }

        // Check that the max upload size specified in class configuration does not
        // exceed size allowed by server config
        if ($this->toBytes(ini_get('post_max_size')) < $this->sizeLimit ||
            $this->toBytes(ini_get('upload_max_filesize')) < $this->sizeLimit){
            $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
            return array('error'=>"Server error. Increase post_max_size and upload_max_filesize to ".$size);
        }

        // is_writable() is not reliable on Windows (http://www.php.net/manual/en/function.is-executable.php#111146)
        // The following tests if the current OS is Windows and if so, merely checks if the folder is writable;
        // otherwise, it checks additionally for executable status (like before).

        $isWin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
        $folderInaccessible = ($isWin) ? !is_writable($uploadDirectory) : ( !is_writable($uploadDirectory) && !is_executable($uploadDirectory) );

        if ($folderInaccessible){
            return array('error' => "Server error. Uploads directory isn't writable" . (!$isWin) ? " or executable." : ".");
        }

        if(!isset($_SERVER['CONTENT_TYPE'])) {
            return array('error' => "No files were uploaded.");
        } else if (strpos(strtolower($_SERVER['CONTENT_TYPE']), 'multipart/') !== 0){
            return array('error' => "Server error. Not a multipart request. Please set forceMultipart to default value (true).");
        }

        // Get size and name

        $file = $_FILES[$this->inputName];
        $size = $file['size'];

        if ($name === null){
            $name = $this->getName();
        }

        // Validate name

        if ($name === null || $name === ''){
            return array('error' => 'File name empty.');
        }

        // Validate file size

        if ($size == 0){
            return array('error' => 'File is empty.');
        }

        if ($size > $this->sizeLimit){
            return array('error' => 'File is too large.');
        }

        // Validate file extension

        $pathinfo = pathinfo($name);
        $ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : '';

        if($this->allowedExtensions && !in_array(strtolower($ext), array_map("strtolower", $this->allowedExtensions))){
            $these = implode(', ', $this->allowedExtensions);
            return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
        }

        // Save a chunk

        $totalParts = isset($_REQUEST['qqtotalparts']) ? (int)$_REQUEST['qqtotalparts'] : 1;

        if ($totalParts > 1){

            $chunksFolder = $this->chunksFolder;
            $partIndex = (int)$_REQUEST['qqpartindex'];
            $uuid = $_REQUEST['qquuid'];

            if (!is_writable($chunksFolder) && !is_executable($uploadDirectory)){
                return array('error' => "Server error. Chunks directory isn't writable or executable.");
            }

            $targetFolder = $this->chunksFolder.DIRECTORY_SEPARATOR.$uuid;

            if (!file_exists($targetFolder)){
                mkdir($targetFolder);
            }

            $target = $targetFolder.'/'.$partIndex;
            $success = move_uploaded_file($_FILES[$this->inputName]['tmp_name'], $target);

            // Last chunk saved successfully
            if ($success AND ($totalParts-1 == $partIndex)){

                $target = $this->getUniqueTargetPath($uploadDirectory, $name);
                $this->uploadName = basename($target);

                $target = fopen($target, 'wb');

                for ($i=0; $i<$totalParts; $i++){
                    $chunk = fopen($targetFolder.DIRECTORY_SEPARATOR.$i, "rb");
                    stream_copy_to_stream($chunk, $target);
                    fclose($chunk);
                }

                // Success
                fclose($target);

                for ($i=0; $i<$totalParts; $i++){
                    unlink($targetFolder.DIRECTORY_SEPARATOR.$i);
                }

                rmdir($targetFolder);

                return array("success" => true);

            }

            return array("success" => true);

        } else {

            $target = $this->getUniqueTargetPath($uploadDirectory, $name);

            if ($target){
                $this->uploadName = basename($target);

                if (move_uploaded_file($file['tmp_name'], $target)){
                    return array('success'=> true);
                }
            }

            return array('error'=> 'Could not save uploaded file.' .
                'The upload was cancelled, or server error encountered');
        }
    }

    /**
     * Returns a path to use with this upload. Check that the name does not exist,
     * and appends a suffix otherwise.
     * @param string $uploadDirectory Target directory
     * @param string $filename The name of the file to use.
     */
    protected function getUniqueTargetPath($uploadDirectory, $filename)
    {
        // Allow only one process at the time to get a unique file name, otherwise
        // if multiple people would upload a file with the same name at the same time
        // only the latest would be saved.

        if (function_exists('sem_acquire')){
            $lock = sem_get(ftok(__FILE__, 'u'));
            sem_acquire($lock);
        }

        $pathinfo = pathinfo($filename);
        $base = $pathinfo['filename'];
        $ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : '';
        $ext = $ext == '' ? $ext : '.' . $ext;

        $unique = $base;
        $suffix = 0;

        // Get unique file name for the file, by appending random suffix.

        while (file_exists($uploadDirectory . DIRECTORY_SEPARATOR . $unique . $ext)){
            $suffix += rand(1, 999);
            $unique = $base.'-'.$suffix;
        }

        $result =  $uploadDirectory . DIRECTORY_SEPARATOR . $unique . $ext;

        // Create an empty target file
        if (!touch($result)){
            // Failed
            $result = false;
        }

        if (function_exists('sem_acquire')){
            sem_release($lock);
        }

        return $result;
    }

    /**
     * Deletes all file parts in the chunks folder for files uploaded
     * more than chunksExpireIn seconds ago
     */
    protected function cleanupChunks(){
        foreach (scandir($this->chunksFolder) as $item){
            if ($item == "." || $item == "..")
                continue;

            $path = $this->chunksFolder.DIRECTORY_SEPARATOR.$item;

            if (!is_dir($path))
                continue;

            if (time() - filemtime($path) > $this->chunksExpireIn){
                $this->removeDir($path);
            }
        }
    }

    /**
     * Removes a directory and all files contained inside
     * @param string $dir
     */
    protected function removeDir($dir){
        foreach (scandir($dir) as $item){
            if ($item == "." || $item == "..")
                continue;

            unlink($dir.DIRECTORY_SEPARATOR.$item);
        }
        rmdir($dir);
    }

    /**
     * Converts a given size with units to bytes.
     * @param string $str
     */
    protected function toBytes($str){
        $val = trim($str);
        $last = strtolower($str[strlen($str)-1]);
        switch($last) {
            case 'g': $val *= 1024;
            case 'm': $val *= 1024;
            case 'k': $val *= 1024;
        }
        return $val;
    }
}

当我上传为文件时,出现以下两个错误,并且文件上传失败:

When I upload as file, I get the follwing two errors and my file upload fails:

错误1

OPTIONS file:///C:/Users/upload/qqFileUploader  jquery.fineuploader-3.4.1.js:3903
handleStandardFileUpload jquery.fineuploader-3.4.1.js:3903
api.upload jquery.fineuploader-3.4.1.js:3989
upload jquery.fineuploader-3.4.1.js:3041
qq.FineUploaderBasic._upload jquery.fineuploader-3.4.1.js:1437
qq.FineUploaderBasic._uploadFileOrBlobDataList jquery.fineuploader-3.4.1.js:1415
qq.FineUploaderBasic.addFiles jquery.fineuploader-3.4.1.js:1049
qq.FineUploaderBasic._onInputChange jquery.fineuploader-3.4.1.js:1340
qq.UploadButton.onChange jquery.fineuploader-3.4.1.js:1117
(anonymous function) jquery.fineuploader-3.4.1.js:680

错误2

[FineUploader] Error when attempting to parse xhr response text (SyntaxError: Unexpected end of input) jquery.fineuploader-3.4.1.js:155
qq.log jquery.fineuploader-3.4.1.js:155
qq.FineUploaderBasic.log jquery.fineuploader-3.4.1.js:939
qq.UploadHandler.log jquery.fineuploader-3.4.1.js:1146
parseResponse jquery.fineuploader-3.4.1.js:3683
onComplete jquery.fineuploader-3.4.1.js:3732
(anonymous function) jquery.fineuploader-3.4.1.js:3766

当debug设置为true时,我得到了:

When debug is set to true, I get this:

[FineUploader] xhr - server response received for 0 jquery.fineuploader-3.4.1.js:150
[FineUploader] responseText = <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL php/qqFileUploader.php was not found on this server.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at Port 80</address>
</body></html>

推荐答案

您尚未正确设置端点,它会出现.您的终结点必须是指向服务器设置上的位置的相对URL或绝对URL,才能处理Fine Uploader的请求.看起来您可能未在网络服务器上运行您的应用程序.似乎您只是在打开Web浏览器并指向文件系统上的html文件.那永远都行不通.

You haven't set your endpoint correctly, it appears. Your endpoint must be a relative or absolute URL pointing at the location on your server setup to handle Fine Uploader's requests. It also looks like you may not be running your app in a webserver. It seems like you are simply opening up a web browser and pointing at an html file on your filesystem. That is never going to work.

请参阅fineuploader.com上的演示以及自述文件中请求选项文档.

Please see the demos on fineuploader.com as well as the request option documentation in the readme.

这篇关于精细上传器实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆