2013-08-16 34 views
0

我一直在试验罚款上传。我对分块和恢复功能非常感兴趣,但我在将文件放回服务器端时遇到了困难;罚款上传PHP服务器端合并

我发现的是,我必须允许服务器端的空白文件扩展名以允许上传块,否则上传将失败,并显示未知文件类型。它可以上传文件名称,如“blob”和“blob63”(无文件扩展名),但在上传完成后不会合并它们。

任何帮助或指针,将不胜感激。

$('#edit-file-uploader').fineUploader({ 
      request: { 
       endpoint: 'upload.php' 
      }, 
      multiple: false, 
      validation:{ 
       allowedExtentions: ['stl', 'obj', '3ds', 'zpr', 'zip'], 
       sizeLimit: 104857600 // 100mb * 1024 (kb) * 1024 (bytes) 
      }, 
      text: { 
       uploadButton: 'Select File' 
      }, 
      autoUpload: false, 
      chunking: { 
       enabled: true 
      }, 
      callbacks: { 
       onComplete: function(id, fileName, responseJSON) { 
        if (responseJSON.success) { 
        /** some code here **?? 
        } 
      } 

    }); 

这是服务器端脚本(PHP):

// list of valid extensions, ex. array("stl", "xml", "bmp") 
$allowedExtensions = array("stl", ""); 
// max file size in bytes 
$sizeLimit = null; 

$uploader = new qqFileUploader($allowedExtensions, $sizeLimit); 

// Call handleUpload() with the name of the folder, relative to PHP's getcwd() 
$result = $uploader->handleUpload('uploads/'); 

// to pass data through iframe you will need to encode all html tags 
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES); 

/******************************************/ 



/** 
* Handle file uploads via XMLHttpRequest 
*/ 
class qqUploadedFileXhr { 
    /** 
    * Save the file to the specified path 
    * @return boolean TRUE on success 
    */ 
    public function save($path) {  
     $input = fopen("php://input", "r"); 
     $temp = tmpfile(); 
     $realSize = stream_copy_to_stream($input, $temp); 
     fclose($input); 

     if ($realSize != $this->getSize()){    
      return false; 
     } 

     $target = fopen($path, "w");   
     fseek($temp, 0, SEEK_SET); 
     stream_copy_to_stream($temp, $target); 
     fclose($target); 

     return true; 
    } 

    /** 
    * Get the original filename 
    * @return string filename 
    */ 
    public function getName() { 
     return $_GET['qqfile']; 
    } 

    /** 
    * Get the file size 
    * @return integer file-size in byte 
    */ 
    public function getSize() { 
     if (isset($_SERVER["CONTENT_LENGTH"])){ 
      return (int)$_SERVER["CONTENT_LENGTH"];    
     } else { 
      throw new Exception('Getting content length is not supported.'); 
     }  
    } 
} 

/** 
* Handle file uploads via regular form post (uses the $_FILES array) 
*/ 
class qqUploadedFileForm { 

    /** 
    * Save the file to the specified path 
    * @return boolean TRUE on success 
    */ 
    public function save($path) { 
     return move_uploaded_file($_FILES['qqfile']['tmp_name'], $path); 
    } 

    /** 
    * Get the original filename 
    * @return string filename 
    */ 
    public function getName() { 
     return $_FILES['qqfile']['name']; 
    } 

    /** 
    * Get the file size 
    * @return integer file-size in byte 
    */ 
    public function getSize() { 
     return $_FILES['qqfile']['size']; 
    } 
} 

/** 
* Class that encapsulates the file-upload internals 
*/ 
class qqFileUploader { 
    private $allowedExtensions; 
    private $sizeLimit; 
    private $file; 
    private $uploadName; 

    /** 
    * @param array $allowedExtensions; defaults to an empty array 
    * @param int $sizeLimit; defaults to the server's upload_max_filesize setting 
    */ 
    function __construct(array $allowedExtensions = null, $sizeLimit = null){ 
     if($allowedExtensions===null) { 
      $allowedExtensions = array(); 
     } 
     if($sizeLimit===null) { 
      $sizeLimit = $this->toBytes(ini_get('upload_max_filesize')); 
     } 

     $allowedExtensions = array_map("strtolower", $allowedExtensions); 

     $this->allowedExtensions = $allowedExtensions;   
     $this->sizeLimit = $sizeLimit; 

     $this->checkServerSettings();  

     if(!isset($_SERVER['CONTENT_TYPE'])) { 
      $this->file = false;  
     } else if (strpos(strtolower($_SERVER['CONTENT_TYPE']), 'multipart/') === 0) { 
      $this->file = new qqUploadedFileForm(); 
     } else { 
      $this->file = new qqUploadedFileXhr(); 
     } 
    } 

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

    /** 
    * Get the original filename 
    * @return string filename 
    */ 
    public function getName(){ 
     if ($this->file) 
      return $this->file->getName(); 
    } 

    /** 
    * Internal function that checks if server's may sizes match the 
    * object's maximum size for uploads 
    */ 
    private function checkServerSettings(){   
     $postSize = $this->toBytes(ini_get('post_max_size')); 
     $uploadSize = $this->toBytes(ini_get('upload_max_filesize'));   

     if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){ 
      $size = max(1, $this->sizeLimit/1024/1024) . 'M';    
      die(json_encode(array('error'=>'increase post_max_size and upload_max_filesize to ' . $size)));  
     }   
    } 

    /** 
    * Convert a given size with units to bytes 
    * @param string $str 
    */ 
    private 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; 
    } 

    /** 
    * Handle the uploaded file 
    * @param string $uploadDirectory 
    * @param string $replaceOldFile=true 
    * @returns array('success'=>true) or array('error'=>'error message') 
    */ 
    function handleUpload($uploadDirectory, $replaceOldFile = FALSE){ 
     if (!is_writable($uploadDirectory)){ 
      return array('error' => "Server error. Upload directory isn't writable."); 
     } 

     if (!$this->file){ 
      return array('error' => 'No files were uploaded.'); 
     } 

     $size = $this->file->getSize(); 

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

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

     $pathinfo = pathinfo($this->file->getName()); 
     $filename = $pathinfo['filename']; 
     //$filename = md5(uniqid()); 
     $ext = @$pathinfo['extension'];  // hide notices if extension is empty 

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

     $ext = ($ext == '') ? $ext : '.' . $ext; 

     if(!$replaceOldFile){ 
      /// don't overwrite previous files that were uploaded 
      while (file_exists($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)) { 
       $filename .= rand(10, 99); 
      } 
     } 

     $this->uploadName = $filename . $ext; 

     if ($this->file->save($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)){ 
      return array('success'=>true); 
     } else { 
      return array('error'=> 'Could not save uploaded file.' . 
       'The upload was cancelled, or server error encountered'); 
     } 

    }  
} 

回答

1

为了处理分块请求,你必须在你的文件系统分开存储每个块。
如何命名这些块或存储它们的位置由您决定,但我建议您使用Fine Uploader提供的UUID对它们进行命名,并附加每个分块请求中包含的零件号参数。在发送完最后一个块之后,将所有块合并到一个文件中,并输入正确的名称,然后返回Fine Uploader文档中所述的标准成功响应。默认情况下,该文件的原始名称在每个请求中都会传入一个qqfilename参数。这也在docsblog中讨论。

它看起来不像你已经尝试处理块服务器端。您可以使用Widen/fine-uploader-server repo中的PHP example。此外,该文档还有一个“服务器端”部分,详细说明如何处理分块。我猜你没看过这个。看看。)在Widen/fine-uploader-server回购中,你可以使用。此外,该文档还有一个“服务器端”部分,详细说明如何处理分块。我猜你没看过这个。看一看。

请注意,从Fine Uploader 3.8(很快发布)开始,您将能够将所有服务器端上传处理委托给Amazon S3,因为Fine Uploader将提供与S3的紧密集成,以发送所有文件直接从浏览器直接到你的存储桶,而无需担心构建策略文档,进行REST API调用,处理来自S3的响应等等。我提到这一点,因为使用S3意味着您无需担心如何处理分块请求你的服务器再次。

相关问题