引言

作为前端开发者,你可能经常需要与服务器文件系统交互。本文将详细介绍如何通过PHP配合Apache实现服务器端文件管理功能。即使你没有任何PHP经验,也能按照本教程实现完整解决方案!

系统准备

PHP下载与安装

  1. 访问PHP官网下载页面

  2. 选择与Apache匹配的版本:

    • Apache版本:2.4.x

    • PHP版本:8.4.x TS (Thread Safe)(对应64位Apache的文件名应该类似:VS17 x64 Thread Safe,对应32位Apache的文件名应该类似:VS17 x86 Thread Safe)

    • 架构:x64(64位系统)或x86(32位系统)

  3. 解压到目录(如D:\php),目录结构应包含:

    php.exe
    php8apache2_4.dll
    php.ini-development
    ext/ (扩展目录)

Apache配置PHP

编辑conf/httpd.conf文件:

# 加载PHP模块
LoadModule php_module "D:/php/php8apache2_4.dll"# 指定php.ini目录
PHPIniDir "D:/php"# 将.php文件交给PHP处理
AddHandler application/x-httpd-php .php# 关联文件扩展名
<FilesMatch \.php$>SetHandler application/x-httpd-php
</FilesMatch>

验证配置

cd D:\Apache24\bin
httpd -t

看到"Syntax OK"表示配置正确,重启Apache服务:

httpd -k restart

文件管理API实现

创建file_manager.php文件:

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *'); // 测试用,生产环境应移除// 安全配置
$BASE_DIR = realpath(__DIR__ . '/Resources');
$ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt', 'docx'];// 路径验证函数
function validatePath($path) {global $BASE_DIR;$realPath = realpath($BASE_DIR . '/' . $path);return ($realPath && strpos($realPath, $BASE_DIR) === 0) ? $realPath : false;
}// 获取目录结构
function listDirectory($path) {$realPath = validatePath($path);if (!$realPath || !is_dir($realPath)) {return ['error' => '无效目录路径'];}$result = [];$items = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($realPath, FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::SELF_FIRST);foreach ($items as $item) {$relativePath = substr($item->getPathname(), strlen($realPath)) ?: '/';$relativePath = ltrim(str_replace('\\', '/', $relativePath), '/');$result[] = ['name' => $item->getFilename(),'path' => $relativePath,'type' => $item->isDir() ? 'directory' : 'file','size' => $item->isFile() ? $item->getSize() : 0,'modified' => date('Y-m-d H:i:s', $item->getMTime())];}return $result;
}// 主请求处理
$response = ['status' => 'error', 'message' => '无效请求'];
$request = json_decode(file_get_contents('php://input'), true) ?? $_REQUEST;try {if (!isset($request['action'])) {throw new Exception('未指定操作');}$action = $request['action'];switch ($action) {case 'list':$path = $request['path'] ?? '';$data = listDirectory($path);$response = ['status' => 'success', 'data' => $data];break;case 'create-folder':$path = $request['path'] ?? '';$name = $request['name'] ?? '';if (empty($name)) throw new Exception('文件夹名称不能为空');$realPath = validatePath($path);if (!$realPath) throw new Exception('无效路径');// 清理文件夹名称$cleanName = preg_replace('/[^a-zA-Z0-9_-]/', '', $name);$newFolder = $realPath . DIRECTORY_SEPARATOR . $cleanName;if (file_exists($newFolder)) {throw new Exception('文件夹已存在');}if (!mkdir($newFolder, 0755)) {throw new Exception('创建文件夹失败');}$response = ['status' => 'success', 'message' => '文件夹创建成功'];break;case 'delete-folder':$path = $request['path'] ?? '';$realPath = validatePath($path);if (!$realPath || !is_dir($realPath)) {throw new Exception('无效目录路径');}// 安全措施:防止删除根目录if ($realPath === $BASE_DIR) {throw new Exception('不能删除根目录');}// 递归删除$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($realPath, FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST);foreach ($files as $file) {if ($file->isDir()) {rmdir($file->getRealPath());} else {unlink($file->getRealPath());}}if (!rmdir($realPath)) {throw new Exception('删除文件夹失败');}$response = ['status' => 'success', 'message' => '文件夹已删除'];break;case 'rename':$type = $request['type'] ?? 'file';$path = $request['path'] ?? '';$newName = $request['newName'] ?? '';if (empty($newName)) throw new Exception('新名称不能为空');$realPath = validatePath($path);if (!$realPath) throw new Exception('无效路径');// 清理新名称$cleanName = preg_replace('/[^a-zA-Z0-9_.-]/', '', $newName);$newPath = dirname($realPath) . DIRECTORY_SEPARATOR . $cleanName;if (file_exists($newPath)) {throw new Exception('目标名称已存在');}if (!rename($realPath, $newPath)) {throw new Exception('重命名失败');}$response = ['status' => 'success', 'message' => '重命名成功'];break;case 'upload-file':$targetPath = $request['path'] ?? '';$realPath = validatePath($targetPath);if (!$realPath || !is_dir($realPath)) {throw new Exception('无效目标目录');}if (empty($_FILES['file'])) {throw new Exception('未选择上传文件');}$file = $_FILES['file'];$filename = preg_replace('/[^a-zA-Z0-9_.-]/', '', basename($file['name']));$targetFile = $realPath . DIRECTORY_SEPARATOR . $filename;$ext = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));// 文件类型验证if (!in_array($ext, $ALLOWED_EXTENSIONS)) {throw new Exception('不允许的文件类型: ' . $ext);}// 防止文件覆盖if (file_exists($targetFile)) {$filename = time() . '_' . $filename;$targetFile = $realPath . DIRECTORY_SEPARATOR . $filename;}if (!move_uploaded_file($file['tmp_name'], $targetFile)) {throw new Exception('文件上传失败');}$response = ['status' => 'success', 'filename' => $filename, 'message' => '文件上传成功'];break;case 'delete-file':$path = $request['path'] ?? '';$realPath = validatePath($path);if (!$realPath || !is_file($realPath)) {throw new Exception('无效文件路径');}if (!unlink($realPath)) {throw new Exception('文件删除失败');}$response = ['status' => 'success', 'message' => '文件已删除'];break;default:throw new Exception('未知操作: ' . $action);}} catch (Exception $e) {$response = ['status' => 'error', 'message' => $e->getMessage()];
}echo json_encode($response);
?>

测试页面

创建file_manager_test.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件管理器测试</title><style>:root {--primary: #3498db;--success: #2ecc71;--danger: #e74c3c;--dark: #34495e;--light: #f8f9fa;}* {box-sizing: border-box;margin: 0;padding: 0;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background-color: #f5f7fa;color: #333;line-height: 1.6;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;background: white;border-radius: 10px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);padding: 30px;}header {text-align: center;margin-bottom: 30px;padding-bottom: 20px;border-bottom: 1px solid #eee;}h1 {color: var(--dark);margin-bottom: 10px;}.subtitle {color: #7f8c8d;font-weight: 400;}.section {margin-bottom: 30px;padding: 25px;border: 1px solid #e1e4e8;border-radius: 8px;background: var(--light);transition: all 0.3s ease;}.section:hover {box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);border-color: #d1d9e0;}.section h2 {color: var(--dark);margin-top: 0;margin-bottom: 20px;padding-bottom: 10px;border-bottom: 1px dashed #ddd;display: flex;align-items: center;}.section h2 i {margin-right: 10px;color: var(--primary);}.form-group {margin-bottom: 20px;display: flex;flex-wrap: wrap;align-items: center;}label {display: inline-block;width: 150px;font-weight: 600;color: #555;}input[type="text"],input[type="file"] {width: calc(100% - 160px);padding: 12px 15px;border: 1px solid #ddd;border-radius: 4px;font-size: 16px;transition: border 0.3s;}input[type="text"]:focus,input[type="file"]:focus {border-color: var(--primary);outline: none;box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);}button {padding: 12px 25px;background: var(--primary);color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;font-weight: 600;transition: all 0.3s;margin-top: 10px;}button:hover {background: #2980b9;transform: translateY(-2px);}.delete-btn {background: var(--danger);}.delete-btn:hover {background: #c0392b;}.radio-group {display: flex;gap: 20px;margin-left: 150px;width: calc(100% - 150px);}.radio-group label {width: auto;display: flex;align-items: center;gap: 5px;font-weight: normal;}.response {margin-top: 20px;padding: 15px;border-radius: 4px;display: none;}.success {background-color: rgba(46, 204, 113, 0.1);border: 1px solid var(--success);color: #27ae60;display: block;}.error {background-color: rgba(231, 76, 60, 0.1);border: 1px solid var(--danger);color: #c0392b;display: block;}pre {background: #2d2d2d;color: #f8f8f2;padding: 15px;border-radius: 4px;max-height: 400px;overflow: auto;margin-top: 15px;font-family: 'Consolas', monospace;}@media (max-width: 768px) {.form-group {flex-direction: column;align-items: flex-start;}label {width: 100%;margin-bottom: 8px;}input[type="text"],input[type="file"] {width: 100%;}.radio-group {margin-left: 0;width: 100%;}}</style>
</head>
<body><div class="container"><header><h1>服务器文件管理器测试</h1><p class="subtitle">通过PHP与Apache实现安全的服务器端文件操作</p></header><!-- 列出目录内容 --><div class="section"><h2><i class="fas fa-folder-open"></i> 列出目录内容</h2><div class="form-group"><label for="listPath">目录路径:</label><input type="text" id="listPath" placeholder="例如: docs/images (留空显示根目录)"></div><button onclick="listDirectory()">列出目录</button><div class="response"><pre id="listResult">目录内容将显示在这里...</pre></div></div><!-- 创建文件夹 --><div class="section"><h2><i class="fas fa-folder-plus"></i> 创建文件夹</h2><div class="form-group"><label for="createPath">父目录路径:</label><input type="text" id="createPath" placeholder="例如: docs"></div><div class="form-group"><label for="folderName">文件夹名称:</label><input type="text" id="folderName" placeholder="例如: new_folder"></div><button onclick="createFolder()">创建文件夹</button><div class="response" id="createResponse"></div></div><!-- 删除文件夹 --><div class="section"><h2><i class="fas fa-trash-alt"></i> 删除文件夹</h2><div class="form-group"><label for="deleteFolderPath">文件夹路径:</label><input type="text" id="deleteFolderPath" placeholder="例如: docs/old_folder"></div><button class="delete-btn" onclick="deleteFolder()">删除文件夹</button><div class="response" id="deleteFolderResponse"></div></div><!-- 重命名文件/文件夹 --><div class="section"><h2><i class="fas fa-i-cursor"></i> 重命名项目</h2><div class="form-group"><label for="renamePath">当前路径:</label><input type="text" id="renamePath" placeholder="例如: docs/image.jpg"></div><div class="form-group"><label for="newName">新名称:</label><input type="text" id="newName" placeholder="例如: new_image.jpg"></div><div class="form-group"><label>类型:</label><div class="radio-group"><label><input type="radio" name="renameType" value="file" checked> 文件</label><label><input type="radio" name="renameType" value="folder"> 文件夹</label></div></div><button onclick="renameItem()">重命名</button><div class="response" id="renameResponse"></div></div><!-- 上传文件 --><div class="section"><h2><i class="fas fa-upload"></i> 上传文件</h2><div class="form-group"><label for="uploadPath">目标目录:</label><input type="text" id="uploadPath" placeholder="例如: docs/uploads"></div><div class="form-group"><label for="fileInput">选择文件:</label><input type="file" id="fileInput"></div><button onclick="uploadFile()">上传文件</button><div class="response" id="uploadResponse"></div></div><!-- 删除文件 --><div class="section"><h2><i class="fas fa-trash-alt"></i> 删除文件</h2><div class="form-group"><label for="deleteFilePath">文件路径:</label><input type="text" id="deleteFilePath" placeholder="例如: docs/file.txt"></div><button class="delete-btn" onclick="deleteFile()">删除文件</button><div class="response" id="deleteFileResponse"></div></div></div><!-- Font Awesome 图标 --><script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"></script><script>const API_URL = 'file_manager.php';// 显示响应消息function showResponse(element, message, isSuccess = true) {element.textContent = message;element.className = 'response ' + (isSuccess ? 'success' : 'error');element.style.display = 'block';// 3秒后淡出setTimeout(() => {element.style.opacity = '1';let opacity = 1;const fadeOut = setInterval(() => {opacity -= 0.05;element.style.opacity = opacity;if (opacity <= 0) {clearInterval(fadeOut);element.style.display = 'none';}}, 50);}, 3000);}// 调用APIasync function callApi(data, files) {const formData = new FormData();// 添加表单数据for (const key in data) {formData.append(key, data[key]);}// 添加文件if (files) {for (const file of files) {formData.append('file', file);}}try {const response = await fetch(API_URL, {method: 'POST',body: formData});return await response.json();} catch (error) {return {status: 'error',message: '网络错误: ' + error.message};}}// 列出目录内容async function listDirectory() {const path = document.getElementById('listPath').value || '';const result = document.getElementById('listResult');result.textContent = '加载中...';const response = await callApi({action: 'list',path: path});if (response.status === 'success') {result.textContent = JSON.stringify(response.data, null, 2);} else {result.textContent = '错误: ' + response.message;}}// 创建文件夹async function createFolder() {const path = document.getElementById('createPath').value || '';const name = document.getElementById('folderName').value;const responseEl = document.getElementById('createResponse');if (!name) {showResponse(responseEl, '文件夹名称不能为空', false);return;}const response = await callApi({action: 'create-folder',path: path,name: name});showResponse(responseEl, response.status === 'success' ? '✅ ' + response.message : '❌ 错误: ' + response.message,response.status === 'success');}// 删除文件夹async function deleteFolder() {const path = document.getElementById('deleteFolderPath').value;const responseEl = document.getElementById('deleteFolderResponse');if (!path) {showResponse(responseEl, '文件夹路径不能为空', false);return;}if (!confirm(`确定要删除文件夹 "${path}" 及其所有内容吗?`)) {return;}const response = await callApi({action: 'delete-folder',path: path});showResponse(responseEl, response.status === 'success' ? '✅ ' + response.message : '❌ 错误: ' + response.message,response.status === 'success');}// 重命名项目async function renameItem() {const path = document.getElementById('renamePath').value;const newName = document.getElementById('newName').value;const type = document.querySelector('input[name="renameType"]:checked').value;const responseEl = document.getElementById('renameResponse');if (!path || !newName) {showResponse(responseEl, '路径和新名称不能为空', false);return;}const response = await callApi({action: 'rename',path: path,newName: newName,type: type});showResponse(responseEl, response.status === 'success' ? '✅ ' + response.message : '❌ 错误: ' + response.message,response.status === 'success');}// 上传文件async function uploadFile() {const path = document.getElementById('uploadPath').value || '';const fileInput = document.getElementById('fileInput');const responseEl = document.getElementById('uploadResponse');if (!fileInput.files || fileInput.files.length === 0) {showResponse(responseEl, '请选择要上传的文件', false);return;}const response = await callApi({action: 'upload-file',path: path}, [fileInput.files[0]]);showResponse(responseEl, response.status === 'success' ? `✅ ${response.message} - 文件名: ${response.filename}` : '❌ 错误: ' + response.message,response.status === 'success');}// 删除文件async function deleteFile() {const path = document.getElementById('deleteFilePath').value;const responseEl = document.getElementById('deleteFileResponse');if (!path) {showResponse(responseEl, '文件路径不能为空', false);return;}if (!confirm(`确定要删除文件 "${path}" 吗?`)) {return;}const response = await callApi({action: 'delete-file',path: path});showResponse(responseEl, response.status === 'success' ? '✅ ' + response.message : '❌ 错误: ' + response.message,response.status === 'success');}</script>
</body>
</html>

关键注意事项

  1. 安全配置

    • 生产环境中移除Access-Control-Allow-Origin: *

    • 添加身份验证(如Basic Auth或API密钥)

    • 限制允许的文件扩展名

    • 设置文件上传大小限制(在php.ini中配置)

  2. 权限设置

    • Windows:为Resources目录添加Apache用户(如SYSTEM)的完全控制权限

    • Linux:chown -R www-data:www-data Resources && chmod -R 755 Resources

  3. 路径说明

    • 列出Resources根目录:输入框留空

    • 列出子目录:直接输入子目录名(如uploads

    • 不要使用前导斜杠(如/uploads

测试流程

  1. 创建Resources目录并设置权限

  2. 上传file_manager.phpfile_manager_test.html到Apache文档根目录

  3. 访问http://localhost/file_manager_test.html

  4. 测试各项功能:

    • 列出目录(留空)

    • 创建测试文件夹

    • 上传文件

    • 重命名/删除操作

补充:

由于前面的php提供的目录树形式过于扁平,这里提供一个返回树形结构的目录的json的php文件。如果要基于这个php文件进行测试,在测试文件file-manager-test.html里面 action:'list'的地方改成action:'get-tree'就可以了。

改进后的file_manager.php:

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');// 配置安全选项
$BASE_DIR = realpath(__DIR__ . '/Resources');
$ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'glb', 'gltf', 'fbx', 'obj', 'txt', 'md'];// 递归获取目录结构
function getDirectoryTree($path) {$realPath = realpath($path);if (!$realPath || !is_dir($realPath)) {return null;}$result = ['name' => basename($realPath),'path' => str_replace($GLOBALS['BASE_DIR'], '', $realPath) ?: '/','type' => 'directory','children' => []];$items = scandir($realPath);foreach ($items as $item) {if ($item === '.' || $item === '..') continue;$itemPath = $realPath . DIRECTORY_SEPARATOR . $item;if (is_dir($itemPath)) {$result['children'][] = getDirectoryTree($itemPath);} else {$ext = strtolower(pathinfo($itemPath, PATHINFO_EXTENSION));$result['children'][] = ['name' => $item,'path' => str_replace($GLOBALS['BASE_DIR'], '', $itemPath),'type' => 'file','size' => filesize($itemPath),'modified' => filemtime($itemPath),'extension' => $ext];}}return $result;
}// 处理请求
$response = ['status' => 'error', 'message' => 'Invalid request'];
$request = json_decode(file_get_contents('php://input'), true) ?? $_REQUEST;try {if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {exit(0);}if (!isset($request['action'])) {throw new Exception('No action specified');}$action = $request['action'];switch ($action) {case 'get-tree':$tree = getDirectoryTree($BASE_DIR);if ($tree) {$response = ['status' => 'success', 'data' => $tree];} else {throw new Exception('Failed to load directory tree');}break;case 'get-files':$path = $request['path'] ?? '/';$realPath = realpath($BASE_DIR . $path);if (!$realPath || !is_dir($realPath)) {throw new Exception('Invalid directory path');}$files = [];$items = scandir($realPath);foreach ($items as $item) {if ($item === '.' || $item === '..') continue;$itemPath = $realPath . DIRECTORY_SEPARATOR . $item;if (!is_dir($itemPath)) {$ext = strtolower(pathinfo($itemPath, PATHINFO_EXTENSION));$files[] = ['name' => $item,'path' => $path . '/' . $item,'type' => 'file','size' => filesize($itemPath),'modified' => filemtime($itemPath),'extension' => $ext];}}$response = ['status' => 'success', 'files' => $files];break;case 'create-folder':$path = $request['path'] ?? '';$name = $request['name'] ?? '';if (empty($name)) throw new Exception('Folder name is required');$realPath = validatePath($path);if (!$realPath) throw new Exception('Invalid path');$newFolder = $realPath . DIRECTORY_SEPARATOR . preg_replace('/[^a-zA-Z0-9_-]/', '', $name);if (file_exists($newFolder)) {throw new Exception('Folder already exists');}if (!mkdir($newFolder)) {throw new Exception('Failed to create folder');}$response = ['status' => 'success', 'message' => 'Folder created'];break;case 'delete-folder':$path = $request['path'] ?? '';$realPath = validatePath($path);if (!$realPath || !is_dir($realPath)) {throw new Exception('Invalid directory path');}// 安全措施:防止删除根目录if ($realPath === $BASE_DIR) {throw new Exception('Cannot delete base directory');}// 递归删除目录$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($realPath, FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST);foreach ($files as $file) {if ($file->isDir()) {rmdir($file->getRealPath());} else {unlink($file->getRealPath());}}if (!rmdir($realPath)) {throw new Exception('Failed to delete folder');}$response = ['status' => 'success', 'message' => 'Folder deleted'];break;case 'rename':$type = $request['type'] ?? ''; // 'file' or 'folder'$path = $request['path'] ?? '';$newName = $request['newName'] ?? '';if (empty($newName)) throw new Exception('New name is required');$realPath = validatePath($path);if (!$realPath) throw new Exception('Invalid path');$newPath = dirname($realPath) . DIRECTORY_SEPARATOR . preg_replace('/[^a-zA-Z0-9_.-]/', '', $newName);if (file_exists($newPath)) {throw new Exception('Target name already exists');}if (!rename($realPath, $newPath)) {throw new Exception('Rename failed');}$response = ['status' => 'success', 'message' => 'Renamed successfully'];break;case 'upload-file':$targetPath = $request['path'] ?? '';$realPath = validatePath($targetPath);if (!$realPath || !is_dir($realPath)) {throw new Exception('Invalid target directory');}if (empty($_FILES['file'])) {throw new Exception('No file uploaded');}$file = $_FILES['file'];$filename = preg_replace('/[^a-zA-Z0-9_.-]/', '', basename($file['name']));$targetFile = $realPath . DIRECTORY_SEPARATOR . $filename;$ext = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));// 验证文件类型if (!in_array($ext, $ALLOWED_EXTENSIONS)) {throw new Exception('File type not allowed');}// 防止覆盖现有文件if (file_exists($targetFile)) {$filename = time() . '_' . $filename;$targetFile = $realPath . DIRECTORY_SEPARATOR . $filename;}if (!move_uploaded_file($file['tmp_name'], $targetFile)) {throw new Exception('File upload failed');}$response = ['status' => 'success', 'filename' => $filename, 'message' => 'File uploaded'];break;case 'delete-file':$path = $request['path'] ?? '';$realPath = validatePath($path);if (!$realPath || !is_file($realPath)) {throw new Exception('Invalid file path');}if (!unlink($realPath)) {throw new Exception('File deletion failed');}$response = ['status' => 'success', 'message' => 'File deleted'];break;default:throw new Exception('Unknown action');}} catch (Exception $e) {$response = ['status' => 'error', 'message' => $e->getMessage()];
}echo json_encode($response);
?>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92330.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92330.shtml
英文地址,请注明出处:http://en.pswp.cn/web/92330.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Word和WPS文字中如何输入汉字的偏旁部首

如何在Word和WPS文字中输入偏旁部首&#xff1f;许多输入法会把常见的偏旁部首直接放到词库&#xff0c;对于词库中没有的可以试试这个方法&#xff1a;先输入一个有这个偏旁部首的字&#xff0c;尽量简单一点的&#xff0c;然后选中这个字插入-符号-其他符号。滚动到这个偏旁部…

day44 力扣1143.最长公共子序列 力扣1035.不相交的线 力扣53. 最大子序和 力扣392.判断子序列

最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&…

应用7:用小白量化智能体金融模块做一个股票选股工具

应用7&#xff1a;用小白量化智能体金融模块做一个股票选股工具 【小白量化智能体】包含有丰富的金融模块。可以让智能体写各种金融量化工具。 我用让小白量化智能体写一个股票选股工具。 我们给【小白量化智能体】一个程序生成话术。 帮我写一个 选股 的应用程序&#xff0c;要…

Qt Frameless Widget跨平台无边框窗口

Qt开发的窗口程序&#xff0c;它的标题栏样式是无法修改的&#xff0c;这个是系统来控制&#xff0c;程序可以调整标题&#xff0c;图标等&#xff0c;但是各个系统可能表现不一致&#xff0c;比如说标题&#xff0c;window10下在标题栏最左边&#xff0c;而UOS则在中间&#x…

使用 IntelliJ IDEA + Spring JdbcTemplate 操作 MySQL 指南

使用 IntelliJ IDEA Spring JdbcTemplate 操作 MySQL 完全指南 一、开发环境搭建&#xff08;基于 IDEA&#xff09; 1. 创建 Spring Boot 项目 打开 IDEA → New Project → Spring Initializr选择&#xff1a; Project SDK: Java 17依赖项&#xff1a;Spring Web, Spring…

从愤怒的小鸟来看Unity武器拖尾的特效优化

目录 前言 素材下载 介绍 官方文档 不添加拖尾的效果 添加拖尾 代码控制拖尾生成 拖尾排序问题 效果 修改拖尾高度和存活时间 效果 待机时无拖尾 效果 参考 前言 在游戏开发过程中&#xff0c;我们经常需要为武器添加拖尾特效&#xff0c;效果如下所示 Unity 自…

Web开发模式 前端渲染 后端渲染 身份认证

Web 开发模式 # 目前主流的Web 开发模式 两种 一、基于 服务器端渲染 的传统 Web开发模式 二、基于 前后端分离 的新型 Web开发模式# 服务端渲染的优缺点# 优点&#xff1a;1. 前端耗时少因为服务端负责动态生成 HTML内容&#xff0c;浏览器&#xff08;包括手…

C++ WonderTrader 源码分析之浮点数处理

介绍 在WonderTrader的文件decimal.h中封装了一些用于浮点数&#xff08;double&#xff09;处理的工具函数&#xff0c;主要目的是解决浮点数精度误差带来的比较问题&#xff0c;以及进行一些常用运算&#xff08;四舍五入、比较、取模等&#xff09;。下面我们逐行详细解释每…

指针——练习

sizeof和strlensizeofsizeof是用来计算变量所占内存空间大小的&#xff0c;单位是字节&#xff0c;如果操作数是类型&#xff0c;计算的是使用类型创建的变量所占内存空间的大小。sizeof只关注占用内存空间的大小&#xff0c;不在乎内存中存放什么数据。我们来看一下这个代码&a…

华为云 Flexus 部署 coze-studio

华为云 Flexus 部署 coze-studio 一、前置 主机和程序&#xff1a;云主机&#xff08;Flexus L ubuntu&#xff09; coze-studio 部署方式&#xff1a;docker&#xff08;提前装好的&#xff09; 字节跳动开源AI智能体开发平台Coze&#xff0c;具备极低的硬件门槛——2核CPU…

Linux系统编程Day7 -- 基于Linux系统知识的第一个程序

往期内容回顾 自动化构建工具-make/Makefile gcc/g编译及链接 Vim工具的使用 Linux常用工具&#xff08;yum与vim&#xff09; ​​​​​​ Linux系统编程Day4-- Shell与权限 编写第一个Linux程序 今天我们要利用我们所学到的Linux语言来编译第一个Linux程序&#xff0c;在进行…

安卓264和265编码器回调编码数据写入.265或者.264文件、查看编码数据是否正确、转换为Mp4文件、查看Mp4文件信息等方法合集

一、写入文件 1、变量定义 private FileOutputStream m265FileOutputStream null; private File m265File null; private static final String HEVC_265_FILE_NAME "output.265"; // 或 .265 private static final String AVC_264_FILE_NAME "output.264&qu…

如何打造一支AI时代下的IT团队,为企业战略目标快速赋能

执行摘要 在当前AI技术迅猛发展的背景下&#xff0c;中国中小企业正面临着前所未有的数字化转型机遇与挑战。据最新调研显示&#xff0c;2025年全球AI市场规模将突破5000亿美元&#xff0c;而中国AI应用占比已达35%。与此同时&#xff0c;AI领域人才缺口高达1000万人&#xff0…

机器学习-LinearRegression

1、 关键数学知识点&#xff1a; 边缘概率密度 联合密度对非关注变量积分&#xff1a;fX(x)∫fX,Y(x,y)dyf_X(x)∫f_{X,Y}(x,y)dyfX​(x)∫fX,Y​(x,y)dy&#xff1b; 条件概率密度 切片 fX∣Y(x∣y)fX,Y(x,y)/fY(y)f_{X|Y}(x|y)f_{X,Y}(x,y)/f_Y(y)fX∣Y​(x∣y)fX,Y​(x,y)…

解决微信小程序中如何把npm构建的模块与主包分离,构建到分包上面

1、配置分包2、复制packge.json到分包中3、在project.config.json中增加npm配置4、终端执行npm i下载模块5、构建npm到miniprogram_npm中

自动驾驶中的传感器技术21——Camera(12)

自动驾驶摄像头的图像评测 摄像头的性能受到环境光照、天气条件、运动模糊等因素的影响&#xff0c;因此需要通过多方面的评测来确保其在各种场景下的可靠性。 在自动驾驶领域&#xff0c;图像质量评估不仅关注图像的清晰度、分辨率等传统指标&#xff0c;还需要结合目标检测…

AI+OA原生应用 麦当秀AIPPT

麦当秀也在WAIC期间重新定义AIOA一、什么是“原生AI”&#xff1f;“原生AI”可以理解为&#xff1a;AI系统本身具备完整的办公能力&#xff0c;不需要依赖传统办公软件&#xff08;如Word、Excel、PPT&#xff09;作为载体。也就是说&#xff0c;用户可以直接通过AI系统完成文…

K8S 入门操作

之前一直用kubectl这个命令操作&#xff0c;这些都是基于命令来操作K8S kubectl get pods kubectl get nodes kubectl get svc kubectl create deployment... kubectl expose deployment...kubectl 文档 命令行工具 (kubectl) | Kubernetes 命令参考 Kubectl Reference Doc…

蒙文OCR识别技术难点实现及应用场景剖析

一、蒙文OCR识别核心技术难点1. 文字特性带来的识别挑战连写特性&#xff1a;蒙文字符存在复杂的连写形式&#xff08;词首、词中、词尾变形&#xff09;方向特异性&#xff1a;传统蒙文为垂直书写&#xff08;现代也有横排&#xff09;&#xff0c;需特殊方向处理字符相似性&a…

通过docker构建一个java镜像

通过docker构建一个java镜像 FROM zlyxzq/centos7:v1 VOLUME /tmp WORKDIR /app COPY /target/aa.jar /root/app/aa.jarENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneENV JAVA_HOME /usr/local/java ENV PA…