如何使用 php 有效地将一个巨大的 JavaScript 字符串存储到文件中


How can you efficiently store a huge javascript string to a file using php?

我有一个网站,它使用javascript和php逐帧生成gif。简而言之,该过程是:

  1. 使用 javascript 生成一个帧(存储为长 base64 编码字符串(
  2. 将此字符串发送到 writeToFile.php ,这将打开一个部分 copmlete 文件并将字符串添加到文件末尾。
  3. 等待成功写入文件,然后转到步骤 1 以获取下一帧

因此,最后,我将创建一个逐个文件,该文件按顺序包含 gif 的所有帧。大多数时候它有效。但是,有时,两个帧会切换,这会使 gif 卡顿(例如,当球击中此 gif 中的柱子时(。

我使用对 php 的调用将其拼凑在一起,并等待它们成功。根据我对 ajax 成功事件的理解,代码应该等到上一帧保存完毕后再生成下一帧,那么 php 怎么可能乱序写入文件呢?

我尝试在 ajax 请求中将异步设置为 false,但仍然会出现卡顿(尽管很少见(。最重要的是,生成速度较慢,因此这不是我理想的解决方案。

爪哇语

//Dostep - The first part of the frame generation. If we aren't done saving to file, wait 100 ms then check again
//This waits until the last frame is generated before generating a new one
var step=(function(){
    var doStep = function () {      
        if (frameSavingToFile){ //Check
            setTimeout(
                 function(){
                      doStep();
                  },
                   100 //if we are saving to file, wait
                 );  
                    return;
         }
        //there is code here I've omitted which moves to the next frame, and stores the string
        saveFrameToFile(frame);
    }
    return function () {
        if (!stepping) setTimeout(doStep, 0);
    };
}
function saveFrameToFile(theEncoder,isLastFrame){
    frameSavingToFile=1;
    var toAppend=window.btoa(theEncoder.stream().getData()); //add in the base 64 to the file
    //save it to a file, on success set frameSavingToFile to 0
    var toPassIn={'fileName':tmpFileName+".gif",'contents':toAppend};
    $.ajax({
      url: "php/writeToFile.php",
       type: "POST",
       data: toPassIn,
       success: function(results) {
           console.log(results);
           frameSavingToFile=0;//we are no longer saving to file
           if (isLastFrame){//this is set to 1 on the last frma
               generationComplete();//don't generate more frames, load the gif for viewing
               return;
           }
       }
    });

}

PHP - 写入文件.php

打开文件,追加框架的内容,然后关闭

<?php
$data = $_POST['contents'];
$fileName = $_POST['fileName'];
$data = base64_decode($data);//puts it in a format I can store
$myfile = fopen('path/to/file/'.$fileName, "a") or die("Unable to open file!");
fwrite($myfile, $data);
fclose($myfile);
?>

代码过于复杂,有超时循环等等。为什么不简单地让 ajax 调用的成功处理程序重新调用以开始下一次写入?

例如

function savedata() {
    var toAppend=window.btoa(theEncoder.stream().getData()); //add in the base 64 to the file
    if (toAppend != '') { // or whatever it takes to see if the encoder's done
      $.ajax(
        blah blah blah,
        success: savedata // keep "looping" until there's nothing left to do
      );
    } else {
       console.log('done');
    }
}

通过这种方式,您只需继续发出 ajax 请求,直到没有更多要保存的数据,一切都会"结束"。您还可以保证在上一个调用完成之前,下一个呼叫不会发出。您还将在每次调用中节省多达 ~99 毫秒的时间,而无需等待超时完成。

默认情况下,

jQuery 中的 ajax 调用是异步的。这意味着它们同时发送到服务器。尝试在$.ajax({})配置对象中设置此标志:async: false

这会阻止 javascript 执行,直到请求从服务器返回。

你的代码不会等待,

  1. 等待成功写入文件,然后转到步骤 1 以获取下一帧

尝试使用同步请求:

 $.ajax({
  url: "php/writeToFile.php",
   type: "POST",
   async: false,
   data: ...

jquery ajax :

异步(默认值:true( 类型:布尔值 默认情况下,发送所有请求 异步(即默认情况下设置为 true(。如果您需要 同步请求,将此选项设置为 false。跨域请求 和数据类型:"jsonp"请求不支持同步操作。 请注意,同步请求可能会暂时锁定浏览器, 在请求处于活动状态时禁用任何操作。