2010-09-08 17 views
9

Tengo un problema en mi máquina de desarrollo que parece estar aislado de esta máquina y no puedo resolverlo. Tengo un cargador de archivos jQuery que publica el archivo seleccionado por el usuario en un script PHP para manejarlo usando XmlHttpRequest. La secuencia de comandos funciona bien en mi MacBook Pro que ejecuta OSX10.6.3 con MAMP 1.9, sin embargo, en mi iMac con el mismo sistema operativo y la misma versión de MAMP, con una imagen de servidor idéntica, falla.

He remontado la causa del error hasta la propiedad $_SERVER["CONTENT_LENGTH"] devolviendo 0, aunque puedo obtener el nombre de archivo muy bien y todo lo demás parece haber tenido éxito sobre la solicitud. Por alguna razón, no parece darme la longitud del contenido real. Aquí está el código que causa el problema: la función en cuestión es getSize().

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"]; //*THIS* is returning 0    
     } else { 
      throw new Exception('Getting content length is not supported.'); 
     }  
    } 
} 
+0

¿Falta algo más? ¿Has probado print_r ($ _ SERVER) e print_r ($ _ POST) para ver todos los campos que está recibiendo tu script? – Jhong

+0

print_r'ing esto me da una gran cantidad de campos, incluyendo la cadena de consulta correcta, el título del script y la ubicación, etc. ¿Hay algo específicamente que debería estar buscando? No puedo pegar toda la respuesta aquí porque son demasiados caracteres. – Sam

Respuesta

3

¿Ha establecido su tipo de codificación en multipart/form-data?

<form action="upload.php" method="post" enctype="multipart/form-data"> 
    ... 
    <input type="file" ... /> 
    ... 
</form> 
+0

Sí, esto es manejado por el plugin jQuery, y la codificación es correcta. – Sam

6

¡Lo solucionó! Parece que la secuencia de comandos de jQuery que estoy utilizando falla en Firefox 3.5.x, actualicé a 3.6.9 y funciona bien.

Ahora tengo que encontrar la manera de volverlo compatible con las versiones anteriores de Firefox.

0

Estoy usando el mismo complemento, la última versión parece funcionar bien incluso con navegadores más antiguos. Todavía tengo algunos problemas de visualización/representación con IE6 e IE7, pero los resolví al hacer el botón opaco y agregar una imagen para cubrirlo. También modifiqué el script PHP receptor para que fuera solo una función en lugar de una función múltiple. No es adecuado para todas las ocasiones, pero funciona bien para mí, para todos los navegadores:

public function web_upload_file_ajax(){ 
    $return    = array(); 
    $uploaded_file  = array('name'=>'', 'size'=>0); 
    // list of valid extensions, ex. array("jpeg", "xml", "bmp") 
    $allowedExtensions = array('jpg', 'jpeg', 'png', 'gif', 'bmp','txt','csv'); 
    // max file size in bytes 
    $sizeLimit   = 3 * 1024 * 1024; 
    //folder to upload the file to - add slash at end 
    $uploadDirectory = TMPPATH.'tmp_upload'.DIRECTORY_SEPARATOR; 
    if(!is_dir($uploadDirectory)){ 
     @mkdir($uploadDirectory, 0766, true); 
    } 
    if(!is_dir($uploadDirectory)){ 
     $return   = array('error' => 'Server error. Impossible to create the cache folder:'.$uploadDirectory); 
    }elseif(!is_writable($uploadDirectory)){ 
     $return   = array('error' => 'Server error. Upload directory is not writable.'); 
    } else { 
     $postSize   = $this->bytes_to_num(ini_get('post_max_size')); 
     $uploadSize   = $this->bytes_to_num(ini_get('upload_max_filesize')); 

     if ($postSize < $sizeLimit || $uploadSize < $sizeLimit){ 
      $size = max(1, $sizeLimit/1024/1024) . 'M'; 
      $return = array('error' => 'increase post_max_size and upload_max_filesize to '.$size); 
     }elseif (isset($_GET['qqfile'])) { 
      $uploaded_file['name'] = $_GET['qqfile']; 
      if (isset($_SERVER['CONTENT_LENGTH'])){ 
       $uploaded_file['size'] = (int)$_SERVER['CONTENT_LENGTH']; 
      } else { 
       $return = array('error'=>'Getting content length is not supported.'); 
      } 
     } elseif (isset($_FILES['qqfile'])) { 
      $uploaded_file['name'] = $_FILES['qqfile']['name']; 
      $uploaded_file['size'] = $_FILES['qqfile']['size']; 
     } else { 
      $return = array('error' => 'No files were uploaded.'); 
     } 
     if(count($return)==0){ 
      if($uploaded_file['size'] == 0)       $return = array('error' => 'File is empty'); 
      elseif($uploaded_file['size'] > $sizeLimit)    $return = array('error' => 'File is too large'); 
      elseif($uploaded_file['name']!=''){ 
       $pathinfo = pathinfo($uploaded_file['name']); 
       $filename = $pathinfo['filename']; 
       $ext  = $pathinfo['extension']; 
       if($allowedExtensions && !in_array(strtolower($ext), $allowedExtensions)){ 
        $return = array('error' => 'File has an invalid extension, it should be one of '.implode(', ', $allowedExtensions).'.'); 
       } 
      } 
     } 
     if(count($return)==0){ 
      // overwrite previous files that were uploaded 
      $filename = ll('sessions')->get_id(); 

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

      $saved = false; 
      $path = $uploadDirectory.$filename.'.'.$ext; 
      if (isset($_GET['qqfile'])) { 
       $input  = fopen('php://input', 'r'); 
       $temp  = tmpfile(); 
       $realSize = stream_copy_to_stream($input, $temp); 
       fclose($input); 

       if ($realSize != $uploaded_file['size']){ 
        $saved = false; 
       } else { 
        $target = fopen($path, 'w'); 
        fseek($temp, 0, SEEK_SET); 
        stream_copy_to_stream($temp, $target); 
        fclose($target); 
        $saved = true; 
       } 
      } else { 
       if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){ 
        $saved = false; 
       } 
       $saved = true; 
      } 
      if ($saved){ 
       $return = array('success'=>true, 'file'=>$filename.'.'.$ext); 
      } else { 
       $return = array('error'=> 'Could not save uploaded file. The upload was cancelled, or server error encountered'); 
      } 
     } 
    } 
    // to pass data through iframe you will need to encode all html tags 
    echo htmlspecialchars(json_encode($return), ENT_NOQUOTES); 
} 

y aquí está la bytes_to_num que utilizo como una función de ayuda, pero puede incluir esto en la misma función, así si que desee:

/** 
* This function transforms bytes (like in the the php.ini notation) for numbers (like '2M') to an integer (2*1024*1024 in this case) 
*/ 
public function bytes_to_num($bytes){ 
    $bytes = trim($bytes); 
    $ret = $bytes+0; 
    if($ret==0 || strlen($ret)>=strlen($bytes)){ 
     return $ret; 
    } 
    $type = substr($bytes, strlen($ret)); 
    switch(strtoupper($type)){ 
     case 'P': 
     case 'Pb': 
      $ret *= 1024; 
     case 'T': 
     case 'Tb': 
      $ret *= 1024; 
     case 'G': 
     case 'Gb': 
      $ret *= 1024; 
     case 'M': 
     case 'Mb': 
      $ret *= 1024; 
     case 'K': 
     case 'Kb': 
      $ret *= 1024; 
      break; 
    } 
    return $ret; 
} 
0
$headers = apache_request_headers(); 
echo $headers['Content-Length']; 

Vamos a suponer éste también devuelve 0?

3

Es posible que se esté utilizando una codificación fragmentada, que no envíe la longitud del contenido.

Cuestiones relacionadas