多个 AJAX 请求时 file_put_contents 访问被拒绝(但已同步)?

4

我正在对一个写请求参数到文件的php文件进行一系列连续(递归)的ajax请求:

make_ajax(s)
{
 var xhr = new XMLHttpRequest();
 xhr.onreadystatechange=function()
 {
  if(this.readyState == 4 && this.status == 200)
  {
   if(s>0)
   make_ajax(s-1)
  }
 };
xhr.open('POST','write.php?s='+s+'&string=somelongstring',true);//url + async/sync
...
xhr.send(null);
}
make_ajax(15);//start request

write.php:

file_put_contents('test.txt',$_GET['s']);

似乎服务器在关闭text.txt文件之前就返回了ajax请求,所以由递归发送的下一个ajax请求会收到访问被拒绝的错误,因为似乎文件仍然被上一个ajax请求打开(即使它已经返回)?我甚至使用async=false测试了这个脚本,但我得到了相同的错误?如何避免php脚本在关闭文件之前返回?
注意:我没有使用会话,我只是将数据发送到服务器以保存在文件中。
注意2:这里我做了一个简单的例子,在实际中我使用这种方法通过ajax和mozSlice方法上传文件块。完整代码:
            function uploadFileXhr(o,start_byte)
            {

                var total=o.size;
                var chunk;

                var peice=1024 * 1024;//bytes to upload at once

                var end_byte=start_byte+peice;
                var peice_count=end_byte/peice;
                $('#debug').html(peice_count);
                var is_last=(total-end_byte<=0)?1:0;
                chunk=o.mozSlice(start_byte, end_byte);

                var xhr = new XMLHttpRequest();//prepare xhr for upload

                xhr.onreadystatechange=function()
                {
                    if(this.readyState == 4 && this.status == 200)
                    {
                        if(is_last==0)
                        {
                            uploadFileXhr(o,end_byte);
                        }
                    }
                };

                xhr.open('POST','upload.php',true);//url + async/sync
                xhr.setRequestHeader("Cache-Control", "no-cache");
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');//header
                xhr.setRequestHeader('Content-Type', 'multipart/form-data');//type for upload
                xhr.send(chunk);//send request of file 
            }
uploadFileXhr(file_input,0);//start recrusive call

upload.php:

$flag =($_GET['start']==0) ? 0:FILE_APPEND;
file_put_contents($remotePath.$add.$file_name, file_get_contents('php://input'),$flag);

注意3:实际上,我找到了一个解决方法来避免这个错误,在upload.php脚本中:

        $flag =($_GET['start']==0) ? 0:FILE_APPEND;
        $file_part=file_get_contents('php://input');
        while(@file_put_contents($remotePath.$add.$file_name, $file_part,$flag)===FALSE)
        {
            usleep(50);
        }

但我仍然无法解释为什么在第一种情况下会出现访问被拒绝的错误,所以等待评论!

你在哪里收到“访问被拒绝”错误?确切的错误消息是什么? - Pekka
file_put_contents() 是阻塞的。脚本在文件关闭之前不会完成。 - rid
这是错误信息:警告:fopen(js/test.txt) [function.fopen]:无法打开流:权限被拒绝,位于C:\wamp\www(我尝试使用标准的fopen和file_put_contents,但是出现了相同的问题)。 - albanx
1
@albanx,如果您有15个并发请求,很可能文件被之前的一个请求锁定了。 - rid
1
你说这是“同步的”,但实际上你的代码是异步的 - 对于同步(阻塞)请求,应该使用xhr.open(...,...,false); - DaveRandom
显示剩余3条评论
1个回答

0

目标文件(test.txt)中是否有任何内容?即第一次请求后是否失败,还是立即失败?该错误表明服务器无法写入文件。这可能是因为其他进程正在使用该文件,或者Web服务器没有对该文件的写入权限。为了排除明显的问题,请确保您的Web服务器实际上被允许写入该文件。


是的,服务器在几秒钟内无法读取文件,我找到了一个解决方案(请参见NOTE3),但我仍然不知道为什么在使用wamp进行本地测试时会出现这种情况。 - albanx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接