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 [1684 просмотра]