简体   繁体   English

在xhr.send(file)之后评估ajax-upload损坏的脚本-有时起作用,有时不起作用

[英]valums ajax-upload broken script after xhr.send(file) - sometimes works, and sometimes does not

I searched for solution to this the better part of the day and I'm still in the dark. 我一天中大部分时间都在寻找解决方案,但我仍然处于黑暗中。 For a client of mine I created a simple web gallery for uploading images and I'm using valums file uploader . 我为我的一个客户创建了一个简单的Web画廊,用于上载图像,并且我正在使用valums文件上载器 Till now I didn't have any problems with it on any other site I created, except miss-configuration which I solved some time ago. 到现在为止,我在创建的任何其他站点上都没有任何问题,除了我之前解决的配置错误。

So, what is the problem? 那么,有什么问题呢?

When I upload a image with filesize below 260KB it works fine. 当我上传文件大小低于260KB的图像时,它可以正常工作。 But, when I'm uploading a bigger image, it doesn't throw me back any error. 但是,当我上传更大的图像时,它不会使我退回任何错误。 I just get an empty thumbnail, because image wasn't uploaded. 我只是得到一个空的缩略图,因为没有上传图像。

When I open Chrome Console, this is what I see: 当我打开Chrome控制台时,会看到以下内容:

 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 

On some occasions I got 413 error "Request entity too large". 在某些情况下,我收到413错误“请求实体太大”。

Let me say that this problem really annoys me because the script works well on my local web server (apache) and on my web server . 我说这个问题确实让我很烦, 因为该脚本在我的本地Web服务器(Apache)和Web服务器上都能很好地工作 Here I can upload as may and as big images as I can find, but on the client's web server... 在这里,我可以上传尽可能多的图像,但可以在客户端的网络服务器上...

If anyone have time and will to help me, here is the JavaScript that I use to call the valums uploader: 如果有人有时间并且会帮助我,这是我用来调用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;

And here is my PHP for server processing the file: 这是我的用于服务器处理文件的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);

Let me say again, all the calls to MySQL, files with require() are valid. 我再说一遍,所有对MySQL的调用以及带有require()的文件都是有效的。 The scripts work on two other servers, but on this one, not. 这些脚本可在其他两台服务器上运行,但不能在另一台服务器上运行。

Thank you for your time and will to help. 感谢您的宝贵时间,并会为您提供帮助。

You have some configuration issues on your server if it is choking due to the content-type header. 如果由于内容类型标头而使服务器阻塞,则服务器上会有一些配置问题。 Instead of commenting out this line, to work around this messed up server, you should perhaps try to set the forceMultipart option to true, assuming your server can handle multipart-encoded requests correctly. 要解决此混乱的服务器,不要注释掉这一行,而应假设服务器可以正确处理多部分编码的请求,您应该尝试将forceMultipart选项设置为true。 This all assumes you are using the 2.1-SNAPSHOT version of the uploader, as the option I mentioned first appeared in this version. 所有这些都假设您使用的是2.1-SNAPSHOT版本的上传程序,因为我提到的选项首先出现在该版本中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM