初步完成上传功能

为了个进度条整了一堆活
目前功能还没有完善(包括文件重复的检测)
This commit is contained in:
Chenx221 2024-02-13 20:44:01 +08:00
parent efd40e3982
commit 468b37b85a
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
5 changed files with 136 additions and 6 deletions

View File

@ -3,6 +3,7 @@
namespace app\controllers; namespace app\controllers;
use app\models\RenameForm; use app\models\RenameForm;
use app\models\UploadForm;
use app\utils\FileTypeDetector; use app\utils\FileTypeDetector;
use Yii; use Yii;
use yii\filters\VerbFilter; use yii\filters\VerbFilter;
@ -10,10 +11,12 @@ use yii\helpers\ArrayHelper;
use yii\web\Controller; use yii\web\Controller;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\web\Response; use yii\web\Response;
use yii\web\UploadedFile;
class HomeController extends Controller class HomeController extends Controller
{ {
protected string $pattern = '/^[^\p{C}\/:*?"<>|\\\\]+$/u'; protected string $pattern = '/^[^\p{C}\/:*?"<>|\\\\]+$/u';
public function behaviors() public function behaviors()
{ {
return array_merge( return array_merge(
@ -26,6 +29,7 @@ class HomeController extends Controller
'download' => ['GET'], 'download' => ['GET'],
'rename' => ['POST'], 'rename' => ['POST'],
'delete' => ['POST'], 'delete' => ['POST'],
'upload' => ['POST'],
], ],
], ],
] ]
@ -254,4 +258,39 @@ class HomeController extends Controller
} }
return true; return true;
} }
/**
* 文件上传
* https://devs.chenx221.cyou:8081/index.php?r=home%2Fupload
*
* @return string|Response
*/
public function actionUpload()
{
$model = new UploadForm();
$model->targetDir = Yii::$app->request->post('targetDir', '.');
$uploadedFiles = UploadedFile::getInstancesByName('files');
$successCount = 0;
$totalCount = count($uploadedFiles);
foreach ($uploadedFiles as $uploadedFile) {
$model->uploadFile = $uploadedFile;
if (!preg_match($this->pattern, $model->uploadFile->baseName)) {
continue;
}
if ($model->upload()) {
$successCount++;
}
}
if ($successCount === $totalCount) {
Yii::$app->session->setFlash('success', 'All files uploaded successfully.');
} elseif ($successCount > 0) {
Yii::$app->session->setFlash('warning', 'Some files uploaded successfully.');
} else {
Yii::$app->session->setFlash('error', 'Failed to upload files.');
}
//返回状态码200
return Yii::$app->response->statusCode = 200; // 如果出错请删掉return
}
} }

48
models/UploadForm.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/*
* 这里的代码借鉴了 https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload
*/
namespace app\models;
use Yii;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
public UploadedFile|null $uploadFile;
public $targetDir; //相对路径
public function rules()
{
return [
[['uploadFile'], 'file', 'skipOnEmpty' => false, 'checkExtensionByMimeType' => false], //这规则奇怪的放走近科学都可以拍好几集了
];
}
public function upload()
{
if ($this->validate()) {
if ($this->targetDir === null) {
$this->targetDir = '.';
}
if (str_contains($this->targetDir, '..')) {
return false;
}
$userHomeDir = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id;
$absolutePath = $userHomeDir . '/' . $this->targetDir;
if (!is_dir($absolutePath)) {
return false;
}
$fileName = $this->uploadFile->baseName;
if ($this->uploadFile->extension !== '') {
$fileName .= '.' . $this->uploadFile->extension;
}
$this->uploadFile->saveAs($absolutePath . '/' . $fileName);
return true;
} else {
return false;
}
}
}

View File

@ -7,10 +7,12 @@
/* @var $directory string 当前路径 */ /* @var $directory string 当前路径 */
use app\models\RenameForm; use app\models\RenameForm;
use app\models\UploadForm;
use yii\bootstrap5\ActiveForm; use yii\bootstrap5\ActiveForm;
use yii\bootstrap5\Html; use yii\bootstrap5\Html;
use app\assets\FontAwesomeAsset; use app\assets\FontAwesomeAsset;
use yii\bootstrap5\Modal; use yii\bootstrap5\Modal;
use yii\bootstrap5\Progress;
use yii\helpers\Url; use yii\helpers\Url;
use yii\web\JqueryAsset; use yii\web\JqueryAsset;
use yii\web\View; use yii\web\View;
@ -23,7 +25,7 @@ JqueryAsset::register($this);
$this->registerCssFile('@web/css/home_style.css'); $this->registerCssFile('@web/css/home_style.css');
?> ?>
<div class="home-directory"> <div class="home-directory">
<div class="d-flex justify-content-between align-items-center" style="margin-bottom: 1rem;"> <div class="d-flex justify-content-between align-items-center">
<h1><?= Html::encode($this->title) ?></h1> <h1><?= Html::encode($this->title) ?></h1>
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton"
@ -31,6 +33,10 @@ $this->registerCssFile('@web/css/home_style.css');
<i class="fa-solid fa-arrow-up-from-bracket"></i> 上传文件 <i class="fa-solid fa-arrow-up-from-bracket"></i> 上传文件
</button> </button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li hidden>
<input type="file" id="file-input" name="uploadFile" multiple>
<input type="hidden" name="targetDir" value="<?= $directory ?>" id="target-dir">
</li>
<li><?= Html::button('上传文件', ['class' => 'dropdown-item file-upload-btn']) ?></li> <li><?= Html::button('上传文件', ['class' => 'dropdown-item file-upload-btn']) ?></li>
<li><?= Html::button('上传文件夹', ['class' => 'dropdown-item folder-upload-btn']) ?></li> <li><?= Html::button('上传文件夹', ['class' => 'dropdown-item folder-upload-btn']) ?></li>
<li> <li>
@ -41,6 +47,16 @@ $this->registerCssFile('@web/css/home_style.css');
</div> </div>
</div> </div>
<!--上传进度条-->
<?php
echo Progress::widget([
'percent' => 0,
'barOptions' => ['class' => ['bg-success', 'progress-bar-animated', 'progress-bar-striped']],
'label' => '123', //NMD 不是说可选吗
'options' => ['style' => 'display: none;margin-top: 10px;', 'id' => 'progress-bar']
]);
?>
<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E&#34;);" <nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E&#34;);"
aria-label="breadcrumb"> aria-label="breadcrumb">
<ol class="breadcrumb"> <ol class="breadcrumb">

View File

@ -38,7 +38,8 @@ table a {
} }
.breadcrumb { .breadcrumb {
border-radius: 0.375rem; /*border-radius: 0.375rem;*/
margin-top: 16px;
} }
.breadcrumb .breadcrumb-item { .breadcrumb .breadcrumb-item {

View File

@ -18,8 +18,36 @@ $(document).on('click', '.delete-btn', function () {
$('#deleteModal').modal('show'); $('#deleteModal').modal('show');
}); });
$(document).on('click', '.file-upload-btn', function () { $(document).on('click', '.file-upload-btn', function () {
console.log('你点击了上传文件,但功能尚未实现'); // 触发文件输入元素的点击事件
$('#file-input').click();
}); });
$('#file-input').on('change', function () {
$('#progress-bar').show();
var files = this.files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
formData.append('files[]', files[i]);
}
formData.append('targetDir', $('#target-dir').val());
formData.append('_csrf', $('meta[name="csrf-token"]').attr('content'));
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
var percentComplete = event.loaded / event.total * 100;
$('#progress-bar .progress-bar').css('width', percentComplete + '%').text(Math.round(percentComplete) + '%');
}
};
xhr.onload = function () {
if (xhr.status !== 200) {
alert('An error occurred during the upload.');
}
window.location.reload();
};
xhr.open('POST', 'index.php?r=home%2Fupload');
xhr.send(formData);
});
$(document).on('click', '.folder-upload-btn', function () { $(document).on('click', '.folder-upload-btn', function () {
console.log('你点击了上传文件夹,但功能尚未实现'); console.log('你点击了上传文件夹,但功能尚未实现');
}); });
@ -65,7 +93,5 @@ dropArea.addEventListener('dragleave', function (event) {
} }
}); });
function uploadFile(file) {
console.log('准备上传,但功能尚未实现');
}