为了账号安全,请及时绑定邮箱和手机立即绑定

如何避免PHP / WordPress内存在大文件上传中批量处理数据的致命错误?

如何避免PHP / WordPress内存在大文件上传中批量处理数据的致命错误?

PHP
婷婷同学_ 2022-09-03 15:57:23
我有一个大的CSV文件,我正在上传到WordPress仪表板以导入分类术语。我写了一个小插件,它使用函数来插入每个术语,但是,该函数缓存了大量数据以检查slugs的唯一性和父术语依赖性,尽管将内存分配增加到0.5 Gb,但该进程的内存不足了大约1000个术语。wp_insert_term()我一直想将文件拆分为可管理的块,以便批量处理数据并运行限制为1000或数据行的会话,这样每个进程都会干净利落地终止。我一直在寻找这样的解决方案,并发现了这篇有趣的文章,内容涉及批量图像导入面临的类似问题,它概述了开发人员如何使用javascript通过向服务器和可管理块发送ajax请求来控制批处理过程。它给了我一个想法,即在上传时读取CSV文件,逐行读取它,并向服务器发送ajax请求以处理可管理的行数。这是实现这一目标的更好方法吗?
查看完整描述

1 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

我根据问题中的链接和一些额外的修补开发了以下解决方案。


在WordPress服务器端,当加载javascript文件时,我根据内存分配来确定服务器可以处理的行数,


$limit = ini_get('memory_limit');

$limit = wp_convert_hr_to_bytes($limit) / MB_IN_BYTES; //in MBs.

switch(true){

    case $limit >= 512:

        $limit = 1000;

        break;

    default:

        $limit = 500;

        break;

}

wp_enqueue_script( 'my-javascript-file');

wp_localize_script( 'my-javascript-file', 'cirData', array(

    'limit'=>$limit

));

您应该根据自己的过程确定并设置自己的限制。


在javascript文件中,使用jQuery,


var reader,formData, lineMarker=0, csvLines, isEOF=false, $file, $form ;

  $(document).ready(function(){

    $file = $(':file'); //file input field

    $form = $('form');  //form

    //when the file field changes....

    $file.on('change', function(){

      //check if the file field has a value.

      if($file.val()){

        //setup file reader.

        reader = new FileReader();

        //now listen for when the file is ready to be read.

        reader.addEventListener('load', function (e) {

          csvLines = e.target.result.split("\n");

          batchProcess(); //launch process.

        });

        //when the form is being submitted, start reading the file.

        $(document).on('click', ':submit', function(e){

          e.preventDefault(); //disable normal submit.

          //setup data for the ajax.

          formData = new FormData($form.get(0));


          //read the file and batch request to server.

          reader.readAsBinaryString($file.get(0).files[0]);

        })

      }

    })

  });


  // Methods

  //posting

  function postCSVdata(csvdata){

    formData.set('csvlines', csvdata); //set the current datat to send.

    $.ajax({

      type: 'POST',

      url: $form.attr('action'),

      data: formData,

      contentType: false,

      processData: false,

      cache: false,

      success: function(data){

        var msg ="";

        if(isEOF){ //is this end of the file?

          console.log("success!");

        }else{ //continue reading file.

          console.log("uploaded:"+ Math.round(lineMarker/csvLines.length*100)+"%");

          batchProcess(); //process the next part of the file.

        }

      }

    })

  }

  //batch process.

  function batchProcess(){

    //csvlines is the array containing all the lines read from the file.

    //lineMarker is the index of the last line read.

    var parsedata='', stop = csvLines.length - lineMarker, line='';


    for(var i = 0; i < stop; i++) {

      line = csvLines[i+lineMarker];

      parsedata +=line+"\n"; //add a new line char for server to process.

      //check if max limit of lines server can process is reached.

      if(i>(cirData.limit-2)) break; //batch limit.

    }

    lineMarker += i;

    if(i==stop) isEOF = true;

    postCSVdata(parsedata); //send to server.

  }

这将以服务器能够处理的行块的顺序方式发送多个 AJAX 请求,而不会出现致命的内存错误。


查看完整回答
反对 回复 2022-09-03
  • 1 回答
  • 0 关注
  • 74 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信