2013-08-16 66 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意味着您無需擔心如何處理分塊請求你的服務器再次。

相關問題