БлогNot. PHP: как показывать прогресс во время загрузки файла

PHP: как показывать прогресс во время загрузки файла

Всё в одном файле типа .php. Работает через JQuery с внешнего сайта. Проверил в XAMPP с PHP 8. Выгружает просто под именем filename.тип, но, думаю, легко доработать. Конечно, на очень маленьких файлах прогресс только "мелькнёт" и заметить его мы не успеем.

<?php
$ret = array();
 
if(!session_id())
    session_start();
 
if(isset($_POST["action"]) and $_POST["action"] == "check_upload")
{
    $key = ini_get('session.upload_progress.name');
    $session_name = ini_get("session.upload_progress.prefix") . $_POST[$key];
 
    if(empty($_SESSION[$session_name]))
        exit(json_encode(array('error' => 'Пустая сессия')));
 
    $p = (float)($_SESSION[$session_name]['bytes_processed'] * 100) / $_SESSION[$session_name]['content_length'];
    $p = round($p, 0);
    $ret['progress'] = $p;
    $ret['bytes_upload'] = $_SESSION[$session_name]['bytes_processed'];
    exit(json_encode($ret));
}
 
if(isset($_POST["action"]) and $_POST["action"] == "cancel_upload")
{
    $key = ini_get('session.upload_progress.name');
    $session_name = ini_get("session.upload_progress.prefix") . $_POST[$key];
    $_SESSION[$session_name]['cancel_upload'] = true;
    exit(json_encode($ret));
}
 
if(isset($_POST["action"]) and $_POST["action"] == "upload_modpuck")
{
    $file = $_FILES['upload_file'];
    if(empty($file['name']))
        exit(json_encode(array('error' => 'Файл отсутствует')));
 
    if($file['error'] != UPLOAD_ERR_OK)
        exit(json_encode(array('error' => 'Ошибка при загрузке: error '.$file['error'])));
 
 
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    if(!strlen($ext))
        exit(json_encode(array('error' => 'Отсутствует расширение')));
 
    $size = filesize($file['tmp_name']);
    if(!move_uploaded_file($file['tmp_name'], 'filename.'.$ext))
        exit(json_encode(array('error' => 'Произошла ошибка при копировании')));
 
    $ret['success']  = 'OK';
    $ret['filesize'] = $size;
    $ret['filename'] = 'filename.'.$ext;
    exit(json_encode($ret));
}
?>
<!DOCTYPE HTML>
<html lang="ru">
<head>
  <meta charset="utf-8">
</head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$( document ).ready(function() {
    var timer, check_timer, $progress, $progress_name, xhr;
    var timeout = 1000;
 
    $form = $('form#upload');
    session_prefix = $form.find('input.upload_progress_name').attr('name');
    session_value = $form.find('input.upload_progress_name').val();
 
    $('form#upload').on('change', function(e){
        e.preventDefault();
        if(check_timer)
            return;
 
        let data = new FormData();
        data.append('action', 'upload_modpuck');
        data.append(session_prefix, session_value);
 
        let file = $form.find('input[name=upload_file]').prop('files')[0];
        if(!file)
        {
            alert('Файл не указан');
            return;
        }
        data.append('upload_file', file);
 
        $progress = $form.find('#progress-bar');
        check_timer = true;
 
        xhr = $.ajax({
            url: window.location.href,
            type: 'POST',
            processData: false,
            contentType: false,
            cache:false,
            dataType: 'json',
            data: data,
            beforeSend: function(){
                $progress.text('0%');
                timer = setTimeout(check_upload, timeout);
                $form.find('#cancel-upload').show();
            },
            complete: function(){
                $form.find('#cancel-upload').hide();
                clearTimeout(timer);
                check_timer = false;
            },
            success: function(data){
                if(data.success == 'OK')
                {
                    $progress.text('Загружено');
                }
                else
                {
                    alert(data.error);
                    $progress.text('Ошибка');
                }
                clearTimeout(timer);
                check_timer = false;
            },
            error: function(){
                $progress.text('Прервано');
                clearTimeout(timer);
                check_timer = false;
            }
        });
    });
 
    $('#cancel-upload').on('click', function(e){
        let data = {'action':'cancel_upload'};
        data[session_prefix] = session_value;
        $.ajax({
            url: window.location.href,
            type: 'POST',
            cache:false,
            dataType: 'json',
            data: data,
            complete: function(){
                progress.text('Прервано');
            },
            success: function(data){
                $form.find('#cancel-upload').hide();
                $progress.text('Прервано');
                clearTimeout(timer);
                check_timer = false;
                xhr.abort();
            }
        });
    });
 
    function check_upload(){
        let data = {'action':'check_upload'};
        data[session_prefix] = session_value;
        $.ajax({
            url: window.location.href,
            type: 'POST',
            cache:false,
            dataType: 'json',
            data: data,
            error: function(){
                clearTimeout(timer);
                check_timer = false;
            },
            success: function(data){
                console.log(data);
                if(check_timer)
                    timer = setTimeout(check_upload, timeout);
                if(data && data.hasOwnProperty('progress'))
                    $progress.text(data.progress + '%');
            }
        });
    }
});
</script>
 
<body>
    <form name="upload" id="upload">
        <input type="hidden" name="MAX_FILE_SIZE" value="524288000">
        <input type="hidden" class="upload_progress_name" name="<?php ini_get('session.upload_progress.name');?>" value="upload_file">
        <input type="file" name="upload_file">
        <span id="progress-bar"></span>
        <span><a id="cancel-upload" href="javascript:void(0);" style="display:none">Отменить</a></span>
    </form>
</body>
</html>

06.06.2021, 16:11 [1681 просмотр]


теги: памятка php время jquery

показать комментарии (1)