0

タイトルが誤解を招くものであった場合は申し訳ありません。タイトルで問題を要約する簡単な方法はありません。現在、AJAX ファイルのアップロードを試しています。以前は標準的なファイルのアップロードを行っていましたが、ファイルのアップロードの進行状況を追跡し、ビデオのアップロードが終了し、処理が終了してデータベースに入れられたときにユーザーに通知する進行状況バーを追加することで、アプリケーションのインターフェイスを少し改善しようとしています。

Ajax がスクリプトの実行を終了するために現在動作しているという事実を除いて、ほとんど問題なく動作しています。基本的に、ほとんどの呼び出しはuploadfiles.php. while ループを使用しfeofて進行状況をファイルに記録しています。ファイルは、要求が変更/完了したことをファイルが通知するまでループする別の AJAX によってフェッチされることになっています。

しかし、繰り返しになりますが、何らかの理由で最初の AJAX リクエストがuploadfiles.php実行を完全に終了するまで待機しているため、プログレス バーは移動しません(ファイルのアップロード、処理が完了し、移動され、プログレス バーが無意味になります)。そのため、ログ ファイルの内容を取得する次の AJAX 要求を許可しません。私は次のことを試しました:

  • ob_start(); and ob_end_flush()ファイルがPHPのtmpフォルダーからカスタムtmpフォルダーに移動された直後に行いました
  • Did flush()、これは上記のポイントとまったく同じだと思います
  • 何かが起こることを期待して、ランダムに何かをエコーし​​、再びフラッシュしました

ignore_user_abort()また、ユーザーがページを離れた場合やリクエストが終了または中止された場合でも、リクエストが中止されないようにするために追加しました。

**JS コードは次のとおりです。

    function uploadFiles()
{
    var data2 = new FormData($("#specialform")[0]);

    timestamp = new Date().getUTCMilliseconds();
    timestamp = timestamp.toString();

    data2.append('outputId', timestamp);

    console.log(data2);

    $.ajax({
        type        : "POST",
        url         : "actions/uploadfiles.php",
        data        : data2,
        processData : false,
        contentType : false,
        success: function(data)
        {
            alert('Finished first request');
            getLog();
        },
        error: function (xhr, ajaxOptions, thrownError)
        {
            alert(xhr.responseText);
            alert(thrownError);
        },
        xhr: function ()
        {
            var xhr = new window.XMLHttpRequest();

            xhr.addEventListener("progress", function (evt)
            {
                if (evt.lengthComputable)
                {
                        var percentComplete = evt.loaded / evt.total;
                        console.log(percentComplete);
                        var percentComplete = percentComplete * 100;

                        $("#progressBar").css({ width : percentComplete + '%' });

                        if ( percentComplete >= 100 )
                            xhr.abort();
                }
                else
                        console.log('unable to complete');
            }, false);

            return xhr;
        },
    })
    .fail(function(data)
    {
        console.log(data);
    });

    //return {'error' : 'No files', 'result' : null};
}

function getLog()
{
    if ( finished == false )
    {
        console.log("logs/" + timestamp);

        $.ajax({
            type        : "GET",
            url         : "logs/" + timestamp,
            processData : false,
            contentType : false,
            success: function(data)
            {
                if ( data == "processing" && !processed )
                {
                    alert('processing video');

                    $("#progressBar").css({ 'background-color' : 'yellow' });

                    processed = true;
                }

                if ( data == "done" )
                {
                    alert('finished conversion');

                    $("#progressBar").css({ 'background-color' : 'green' });

                    finished = true;
                }

                if ( $.isNumeric(data) )
                    $("#progressBar").css({ width : data + '%' });

                console.log(data);
            }
        });

        setTimeout(getLog, 1000);
    }
}

PHPコードは次のとおりです。

<?php

require '../Init.php';

define('TMP_PATH', PATH.'/tmp');
define('V_STORE', PATH.'/resources/videos');
define('FFMPEG_PATH', 'F:/Webserver/ffmpeg/bin/ffmpeg.exe');

// ...

ob_start();

echo "END";

ob_end_flush();
flush();

// ...

$remote = fopen($_FILES['file']['tmp_name'], 'r');
$local = fopen($filename, 'w');

$read_bytes = 0;

set_time_limit(28800000);
ignore_user_abort(true);

$interval = 0;

while( !feof($remote) )
{
    $buffer = fread($remote, 2048);
    fwrite($local, $buffer);

    $read_bytes += 2048;

    $progress = min(100, 100 * $read_bytes / $filesize);

    if ( $interval <= 0 )
    {
        file_put_contents('../logs/'.$logFile, $progress);

        $interval = 1000;
    }
    else
        $interval--;
}

// ...

$proc = popen(FFMPEG_PATH.' -i '.$filename.' -b '.$newBitrate.' '.V_STORE.'/'.$video_id.'.mp4', 'r');

while (!feof($proc))
{
    file_put_contents('../logs/'.$logFile, fread($proc, 4096));
}

file_put_contents('../logs/'.$logFile, "done");

sleep(5);

unlink('../logs/'.$logFile);

Init.phpasについて心配する必要はありません(この場合)PATH定数にのみ使用されます

前もって感謝します。

4

1 に答える 1

0

Init.php ファイル (または他の場所) で PHP ファイルベースのセッションを使用していますか? デフォルトでは、これらのファイルはセッションが実質的に閉じられるまでロックされ、一度に 1 つの要求しか実行できません。

その場合は、次を使用してアップロード ファイルのセッションを閉じる必要があります。

session_write_close();
于 2016-05-09T23:28:51.407 に答える