2012-10-09 36 views
0

我在這一天的好時間裏尋找解決方案,我仍然處於黑暗中。對於我的客戶,我創建了一個用於上傳圖片的簡單網絡圖庫,並使用valums file uploader。直到現在,我在我創建的任何其他站點上都沒有任何問題,除了我之前解決的miss-configuration問題。valums ajax-upload xhr.send(文件)後破壞的腳本 - 有時可以使用,有時不會

那麼,這是什麼問題?

當我上傳一個文件大小低於260KB的圖像時,它工作正常。但是,當我上傳更大的圖像時,它不會讓我回到任何錯誤。我只是得到一個空的縮略圖,因爲圖像沒有上傳。

當我打開瀏覽器控制檯,這是我所看到的:

POST http://designflowstudio.com/gallery2/include/upload.php?url=uploads%2Fe558c4dfc2a0f0d60f5ebff474c97ffc&fid=7&qqfile=316267269718409738080100.jpg 403 (Forbidden) fileuploader.js:1463 
POST http://designflowstudio.com/gallery2/include/upload.php?url=uploads%2Fe558c4dfc2a0f0d60f5ebff474c97ffc&fid=7&qqfile=3.jpg 403 (Forbidden) fileuploader.js:1463 

在某些情況下我得到413錯誤「請求實體太大」。

讓我說,這個問題真的讓我很懊惱,因爲腳本在我的本地web服務器(apache)和我的web服務器上運行良好。在這裏,我可以上傳儘可能大的圖片,但我可以在客戶端的網絡服務器上...

如果有人有時間和意願來幫助我,這裏是我用來調用valums上傳器的JavaScript :

 function createUploader(){ 
var uploader = new qq.FileUploaderBasic({ 
    debug: true, 
    multiple: true, 
    allowedExtensions: [<?php $tmp=".";foreach($allowedExt as $ext){$tmp.="'$ext', ";}echo substr($tmp,1,strlen($tmp)-3);?>], 
    button: document.getElementById('uploadDiv'), 
    action: '<?php echo$home;?>include/upload.php', 
    sizeLimit: <?php echo$sizeLimit;?>, 
    forceMultipart: true, 
    params: {'url':'uploads/<?php echo$g['path'];?>','fid':'<?php echo$g['id'];?>'}, 
    onSubmit: function(id, fName){$('#upload-list').append('<div id="upload-list-'+id+'" class="gallery" rel="'+fName+'"><div class="progress'+id+'"></div>');$('.progress'+id).progressbar({value:0})}, 
    onProgress: function(id, fName, loaded, total){ 
    var p = 0; 
    p = parseFloat(loaded/total*100); 
    if(isNaN(p)) p = ''; 
    $('.progress'+id).progressbar("option","value",p); 
    }, 
    onComplete: function(id,fName,json){ 
    if(json.error){ 
    $('#upload-list-'+id).html(fName+'<br />'+json.error); 
    }else{ 
    $('#upload-list-'+id) 
    .attr("rel",json.fname) 
    .html('<img class="cmd" id="deleteImg" rel="'+json.id+'" src="<?php echo$home;?>images/delete.png" title="Delete picture" /><img class="img" src="<?php echo$home;?>uploads/<?php echo$g['path'];?>/th_'+json.fname+'" /><input class="ut" type="text" name="name" value="'+json.name+'" /><input class="ud" type="text" name="desc" /><div class="cl"></div>') 
    .attr("id",json.id); 
    } 
    }, 
    onError: function(id,fName,error){ 
    console.log(id+' '+fName+' '+error); 
    } 
}); 
} 
window.onload = createUploader; 

這裏是我的服務器PHP處理文件:

require("config.php"); 
require("SimpleImage.php"); 
ini_set("log_errors" , "1"); 
ini_set("error_log" , "php-errors-upload.log"); 
ini_set("display_errors" , "1"); 
/** 
* Handle file uploads via XMLHttpRequest 
*/ 
class qqUploadedFileXhr { 
    /** 
    * Save the file to the specified path 
    * @return boolean TRUE on success 
    */ 
    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; 
    } 
    function getName() { 
     return $_GET['qqfile']; 
    } 
    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 
    */ 
    function save($path) { 
     if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){ 
      return false; 
     } 
     return true; 
    } 
    function getName() { 
     return $_FILES['qqfile']['name']; 
    } 
    function getSize() { 
     return $_FILES['qqfile']['size']; 
    } 
} 

class qqFileUploader { 
    private $allowedExtensions = array(); 
    private $sizeLimit = 20485760; 
    private $file; 

    function __construct(array $allowedExtensions = array(), $sizeLimit = 20485760){ 
     $allowedExtensions = array_map("strtolower", $allowedExtensions); 

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

     $this->checkServerSettings(); 

     if (isset($_GET['qqfile'])) { 
      $this->file = new qqUploadedFileXhr(); 
     } elseif (isset($_FILES['qqfile'])) { 
      $this->file = new qqUploadedFileForm(); 
     } else { 
      $this->file = false; 
     } 
    } 

    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("{'error':'increase post_max_size and upload_max_filesize to $size'}");  
     }   
    } 

    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; 
    } 

    /** 
    * Returns array('success'=>true) or array('error'=>'error message') 
    */ 
    function handleUpload($uploadDirectory, $replaceOldFile = FALSE){ 
     chdir("../"); 
     if(!file_exists($uploadDirectory)){ 
      foreach(explode("/",$uploadDirectory) as $val){ 
      if(empty($val2)){$val2=$val."/";}else{$val2.=$val."/";} 
      if($val<>""){if(!file_exists($val2)){mkdir($val2);}} 
      } 
     } 

     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 = md5($pathinfo['filename'].mt_rand()); 
     //$filename = md5(uniqid()); 
     $ext = strtolower($pathinfo['extension']); 

     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 . '.'); 
     } 

     if(!$replaceOldFile){ 
      /// don't overwrite previous files that were uploaded 
      while (file_exists($uploadDirectory . $filename . '.' . $ext)) { 
       $filename .= rand(10, 99); 
      } 
     } 
     if ($this->file->save($uploadDirectory .'/'. $filename . '.' . $ext)){ 
      global $sql_images; 
      $md=md5($filename); 
      $tmp=mysql_query("SELECT `order` FROM `$sql_images` WHERE `gid`='{$_REQUEST['fid']}' ORDER BY `order` DESC"); 
      if($tmp&&mysql_num_rows($tmp)>0){$i=mysql_result($tmp,0);$i++;}else{$i=0;} 
      mysql_query("INSERT INTO `$sql_images` (`order`,`gid`,`name`,`path`) VALUES ('$i','{$_REQUEST['fid']}','{$pathinfo['filename']}','$filename.$ext')"); 
      $image = new SimpleImage(); 
      $image->load($uploadDirectory.'/'.$filename.'.'.$ext); 
      $image->resizeToWidth(150); 
      $image->save($uploadDirectory.'/th_'.$filename.'.'.$ext); 
      return array('success'=>true,'fname'=>$filename.".".$ext,'name'=>$pathinfo['filename'],'id'=>mysql_insert_id()); 
     } else { 
      return array('error'=> 'Could not save uploaded file.' . 
       'The upload was cancelled, or server error encountered'); 
     } 
    } 
} 

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

$uploader = new qqFileUploader($allowedExtensions, $sizeLimit); 
$result = $uploader->handleUpload($_REQUEST['url']); 
// to pass data through iframe you will need to encode all html tags 
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES); 

讓我再說一遍,所有的呼叫到MySQL,文件與要求()是有效的。這些腳本可以在另外兩臺服務器上運行,但是在這一臺服務器上,不是

謝謝你的時間和意願。

+0

嗯,我知道了。 腳本_fileuploader.js_將內容類型設置爲_application/octet-stream_。到目前爲止,所有服務器都很好,但不是這個。當我評論它設置此內容類型的部分時,這開始發揮作用。 我評論部分: 'xhr.setRequestHeader(「內容類型」,「應用/八位字節流」);' 同時,我認爲存在對服務器的mod_security啓用和腐化POST數據。 我發佈這個,希望有一天有人可能需要這些信息。因爲我經常在SO尋找幫助。 乾杯:) –

回答

0

如果由於內容類型標題而導致窒息,那麼您的服務器上有一些配置問題。爲了解決這個混亂的服務器,你應該試着將forceMultipart選項設置爲true,而不是註釋掉這條線,假設你的服務器可以正確處理多部分編碼的請求。這一切都假定您正在使用上傳器的2.1-SNAPSHOT版本,因爲我提到的選項最先出現在此版本中。

+0

我使用的選項** forceMultipart:true **,它沒有改變任何東西。起初我使用舊版本,然後更新到最新版本。錯誤仍然存​​在。 經過一些研究和谷歌搜索之後,我仍然懷疑mod_security存在問題,但客戶並不願意聯繫他的管理員來澄清這一點並更改服務器設置。 此外,上傳者可以使用Chrome,Opera和IE,但不支持Firefox。有些東西將content-Type設置爲「application/octet-stream」,當然,它被拒絕。 也嘗試與內容類型「multipart/form-data」,沒有運氣。 –

+0

XHR POST請求的內容類型在上傳器js代碼中被硬編碼爲application/octet-stream。如果將forceMultipart設置爲true不能解決您的問題,那麼問題不是內容類型。 –

+0

我的意思是,在FireFox中,xhr contentType被設置爲「application/octet-stream」,在我在上傳器js中評論過該行後,在其他瀏覽器中,沒有發送contentType並且上傳正常。我可以對客戶說這是服務器配置錯誤嗎? –