最新图片阅后自焚源码:
使用教程:复制下面代码,命名为index.php即可,需要给写入权限,无需数据库!
PHP源码:
<?php
// 配置区域
define('STORAGE_DIR', __DIR__ . '/storage/');
define('DB_FILE', __DIR__ . '/database.json');
define('MAX_VIEWS_MIN', 1);
define('MAX_VIEWS_MAX', 999);
// 创建必要目录
if (!file_exists(STORAGE_DIR)) {
mkdir(STORAGE_DIR, 0700, true);
}
// 处理文件查看
if (isset($_GET['token'])) {
$token = $_GET['token'];
$db = loadDatabase();
if (isset($db[$token])) {
$entry = $db[$token];
$filePath = STORAGE_DIR . $entry['filename'];
// 检查访问次数
if ($entry['views'] >= $entry['max_views']) {
// 删除文件并移除记录
@unlink($filePath);
unset($db[$token]);
saveDatabase($db);
renderExpiredPage();
exit;
}
// 增加访问计数
$db[$token]['views']++;
saveDatabase($db);
// 输出文件
header('Content-Type: ' . mime_content_type($filePath));
readfile($filePath);
// 检查是否需要销毁
if ($db[$token]['views'] >= $db[$token]['max_views']) {
@unlink($filePath);
unset($db[$token]);
saveDatabase($db);
}
exit;
} else {
renderInvalidLinkPage();
exit;
}
}
// 处理文件上传
$error = '';
$link = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
$maxViews = isset($_POST['views']) ? max(MAX_VIEWS_MIN, min(MAX_VIEWS_MAX, (int)$_POST['views'])) : MAX_VIEWS_MIN;
// 验证文件类型
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($file['type'], $allowedTypes)) {
$error = '只允许上传JPG、PNG、GIF或WEBP图片';
} else if ($file['error'] !== UPLOAD_ERR_OK) {
$error = '文件上传错误: ' . $file['error'];
} else {
// 生成唯一标识
$token = bin2hex(random_bytes(16));
$filename = $token . '_' . basename($file['name']);
$filePath = STORAGE_DIR . $filename;
// 保存文件
if (move_uploaded_file($file['tmp_name'], $filePath)) {
// 保存到数据库
$db = loadDatabase();
$db[$token] = [
'filename' => $filename,
'max_views' => $maxViews,
'views' => 0,
'created' => time()
];
saveDatabase($db);
// 生成访问链接
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME'];
$link = "$protocol://$host$script?token=$token";
} else {
$error = '文件保存失败,请检查目录权限';
}
}
}
// 辅助函数:加载数据库
function loadDatabase() {
if (file_exists(DB_FILE)) {
return json_decode(file_get_contents(DB_FILE), true) ?: [];
}
return [];
}
// 辅助函数:保存数据库
function saveDatabase($data) {
file_put_contents(DB_FILE, json_encode($data, JSON_PRETTY_PRINT));
}
// 渲染过期页面
function renderExpiredPage() {
header("Content-Type: text/html");
echo <<<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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
padding: 20px;
line-height: 1.5;
}
.container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 16px;
padding: 30px 25px;
width: 100%;
max-width: 400px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.2);
margin: 20px;
}
h1 {
font-size: 1.8rem;
margin-bottom: 15px;
font-weight: 600;
text-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
p {
font-size: 1rem;
margin-bottom: 25px;
opacity: 0.9;
}
.icon {
font-size: 3.5rem;
margin-bottom: 20px;
color: #ff6b6b;
text-shadow: 0 0 15px rgba(255, 107, 107, 0.7);
}
.btn {
display: inline-block;
background: #fff;
color: #2575fc;
padding: 12px 28px;
border-radius: 50px;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
border: none;
cursor: pointer;
width: 100%;
max-width: 200px;
}
.btn:active {
transform: scale(0.98);
}
@media (max-width: 480px) {
.container {
padding: 25px 20px;
border-radius: 14px;
}
h1 {
font-size: 1.6rem;
}
}
</style>
</head>
<body>
<div class="container">
<div class="icon">🔥</div>
<h1>文件已自毁</h1>
<p>此文件已达到最大访问次数限制,系统已自动销毁。</p>
<a href="./" class="btn">返回首页</a>
</div>
</body>
</html>
HTML;
}
// 渲染无效链接页面
function renderInvalidLinkPage() {
header("Content-Type: text/html");
echo <<<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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #333;
padding: 20px;
line-height: 1.5;
}
.container {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 16px;
padding: 30px 25px;
width: 100%;
max-width: 400px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
margin: 20px;
}
h1 {
font-size: 1.8rem;
margin-bottom: 15px;
color: #d63031;
font-weight: 600;
}
p {
font-size: 1rem;
margin-bottom: 25px;
opacity: 0.9;
}
.icon {
font-size: 3.5rem;
margin-bottom: 20px;
color: #d63031;
}
.btn {
display: inline-block;
background: #d63031;
color: white;
padding: 12px 28px;
border-radius: 50px;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(214, 48, 49, 0.3);
border: none;
cursor: pointer;
width: 100%;
max-width: 200px;
}
.btn:active {
transform: scale(0.98);
}
@media (max-width: 480px) {
.container {
padding: 25px 20px;
border-radius: 14px;
}
h1 {
font-size: 1.6rem;
}
}
</style>
</head>
<body>
<div class="container">
<div class="icon">⚠️</div>
<h1>链接无效或已过期</h1>
<p>您访问的链接可能已失效、过期或被销毁。</p>
<a href="./" class="btn">返回首页</a>
</div>
</body>
</html>
HTML;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>阅后自焚图片分享</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #1a2a6c;
--secondary-color: #b21f1f;
--text-color: #333;
--light-text: #666;
--bg-color: #f8f9fa;
--card-bg: #fff;
--border-color: #e0e0e0;
--error-color: #e53e3e;
--success-color: #48bb78;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: var(--bg-color);
color: var(--text-color);
line-height: 1.5;
min-height: 100vh;
padding: 0;
margin: 0;
}
.app-container {
max-width: 100%;
width: 100%;
margin: 0 auto;
background: white;
min-height: 100vh;
position: relative;
overflow-x: hidden;
}
/* 头部样式 */
.app-header {
background: linear-gradient(to right, var(--primary-color), var(--secondary-color));
color: white;
padding: 18px 20px;
text-align: center;
position: relative;
}
.app-header h1 {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 5px;
}
.app-header p {
font-size: 0.9rem;
opacity: 0.9;
max-width: 400px;
margin: 0 auto;
}
.header-icon {
position: absolute;
top: 15px;
right: 15px;
font-size: 2rem;
opacity: 0.2;
}
/* 主要内容区 */
.main-content {
padding: 20px;
max-width: 500px;
margin: 0 auto;
}
/* 上传区域 */
.upload-section {
background: var(--card-bg);
border-radius: 14px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
border: 1px solid var(--border-color);
}
.section-title {
display: flex;
align-items: center;
gap: 10px;
font-size: 1.2rem;
margin-bottom: 20px;
color: var(--primary-color);
font-weight: 600;
}
.section-title i {
background: var(--primary-color);
color: white;
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text-color);
font-size: 0.95rem;
}
/* 文件上传区域 */
.file-input {
position: relative;
border: 2px dashed var(--border-color);
border-radius: 12px;
padding: 30px 15px;
text-align: center;
transition: all 0.2s;
background: #f8fafc;
cursor: pointer;
overflow: hidden;
}
.file-input:hover {
border-color: var(--primary-color);
}
.file-input i {
font-size: 2.2rem;
color: var(--primary-color);
margin-bottom: 10px;
}
.file-input p {
margin-bottom: 10px;
color: var(--light-text);
font-size: 0.9rem;
}
.file-input .btn {
display: inline-block;
background: var(--primary-color);
color: white;
padding: 8px 16px;
border-radius: 8px;
font-weight: 500;
transition: all 0.2s;
font-size: 0.9rem;
}
input[type="file"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
/* 计数器样式 */
.counter-container {
display: flex;
flex-direction: column;
gap: 8px;
}
.counter-input {
display: flex;
align-items: center;
gap: 10px;
}
.counter-input input {
flex: 1;
padding: 12px;
border: 2px solid var(--border-color);
border-radius: 10px;
font-size: 1rem;
text-align: center;
transition: border-color 0.2s;
-webkit-appearance: none;
}
.counter-input input:focus {
border-color: var(--primary-color);
outline: none;
}
.counter-btn {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--primary-color);
color: white;
border: none;
font-size: 1.1rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.counter-btn:active {
transform: scale(0.95);
}
/* 提交按钮 */
.submit-btn {
background: linear-gradient(to right, var(--primary-color), var(--secondary-color));
color: white;
border: none;
padding: 14px 0;
border-radius: 12px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
width: 100%;
transition: all 0.2s;
box-shadow: 0 4px 12px rgba(26, 42, 108, 0.2);
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.submit-btn:active {
transform: translateY(1px);
}
/* 结果区域 */
.result-section {
background: var(--card-bg);
border-radius: 14px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
border: 1px solid var(--border-color);
display: none;
}
.result-section.active {
display: block;
}
.link-box {
background: #f0f4f8;
border-radius: 12px;
padding: 16px;
margin-top: 15px;
border: 2px dashed var(--border-color);
}
.link-box p {
font-size: 0.95rem;
margin-bottom: 12px;
color: var(--primary-color);
font-weight: 500;
}
.link-input {
display: flex;
flex-direction: column;
gap: 10px;
}
.link-input input {
flex: 1;
padding: 12px;
border: 2px solid var(--border-color);
border-radius: 10px;
font-size: 0.9rem;
background: white;
width: 100%;
}
.copy-btn {
background: var(--primary-color);
color: white;
border: none;
padding: 12px;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
font-weight: 500;
font-size: 0.95rem;
}
.copy-btn:active {
transform: scale(0.98);
}
/* 信息卡片 */
.info-section {
background: var(--card-bg);
border-radius: 14px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
border: 1px solid var(--border-color);
}
.info-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-top: 15px;
}
.info-card {
background: #f8fafc;
border-radius: 10px;
padding: 15px;
text-align: center;
border-left: 3px solid var(--primary-color);
}
.info-card i {
font-size: 1.8rem;
color: var(--primary-color);
margin-bottom: 10px;
}
.info-card h3 {
font-size: 0.95rem;
margin-bottom: 5px;
color: var(--primary-color);
}
.info-card p {
font-size: 0.8rem;
color: var(--light-text);
}
/* 错误提示 */
.error {
background: #fff5f5;
color: var(--error-color);
padding: 12px;
border-radius: 8px;
margin-top: 15px;
border-left: 3px solid var(--error-color);
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
}
/* 页脚 */
.app-footer {
text-align: center;
padding: 15px 20px;
background: #f8f9fa;
color: var(--light-text);
font-size: 0.8rem;
border-top: 1px solid var(--border-color);
}
/* 响应式调整 */
@media (min-width: 500px) {
.app-container {
max-width: 500px;
margin: 10px auto;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
min-height: calc(100vh - 20px);
}
.link-input {
flex-direction: row;
}
.copy-btn {
width: auto;
padding: 12px 20px;
}
}
/* 动画效果 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-in {
animation: fadeIn 0.3s ease-out forwards;
}
</style>
</head>
<body>
<div class="app-container">
<header class="app-header">
<div class="header-icon">
<i class="fas fa-fire"></i>
</div>
<h1>阅后自焚图片分享</h1>
<p>上传图片并设置访问次数,达到次数后自动销毁</p>
</header>
<main class="main-content">
<section class="upload-section fade-in">
<h2 class="section-title">
<i class="fas fa-cloud-upload-alt"></i>
<span>上传图片</span>
</h2>
<form method="POST" enctype="multipart/form-data" id="upload-form">
<div class="form-group">
<label for="file">选择图片文件</label>
<div class="file-input" id="file-input-area">
<i class="fas fa-file-image"></i>
<p>点击或拖拽文件到此处</p>
<span class="btn">选择文件</span>
<input type="file" name="file" id="file" required accept="image/*">
</div>
</div>
<div class="form-group">
<label for="views">设置最大访问次数 (1-999)</label>
<div class="counter-container">
<div class="counter-input">
<button type="button" class="counter-btn minus">-</button>
<input type="number" name="views" id="views" value="1" min="1" max="999" required>
<button type="button" class="counter-btn plus">+</button>
</div>
<small style="color: var(--light-text);">达到设定次数后文件将自动销毁</small>
</div>
</div>
<?php if (!empty($error)): ?>
<div class="error">
<i class="fas fa-exclamation-circle"></i>
<span><?= htmlspecialchars($error) ?></span>
</div>
<?php endif; ?>
<button type="submit" class="submit-btn">
<i class="fas fa-fire"></i> 生成自焚链接
</button>
</form>
</section>
<section class="result-section <?= !empty($link) ? 'active fade-in' : '' ?>">
<h2 class="section-title">
<i class="fas fa-link"></i>
<span>分享链接</span>
</h2>
<p>您的图片已上传成功!此链接在访问 <strong><?= isset($maxViews) ? $maxViews : 1 ?></strong> 次后将自动销毁。</p>
<div class="link-box">
<p>复制以下链接分享给他人:</p>
<div class="link-input">
<input type="text" id="generated-link" value="<?= !empty($link) ? htmlspecialchars($link) : '' ?>" readonly>
<button class="copy-btn" id="copy-btn">复制链接</button>
</div>
</div>
</section>
<section class="info-section fade-in">
<h2 class="section-title">
<i class="fas fa-info-circle"></i>
<span>使用说明</span>
</h2>
<div class="info-grid">
<div class="info-card">
<i class="fas fa-upload"></i>
<h3>上传图片</h3>
<p>选择要分享的图片</p>
</div>
<div class="info-card">
<i class="fas fa-cog"></i>
<h3>设置次数</h3>
<p>设置允许访问次数</p>
</div>
<div class="info-card">
<i class="fas fa-share-alt"></i>
<h3>分享链接</h3>
<p>复制生成的链接</p>
</div>
<div class="info-card">
<i class="fas fa-fire"></i>
<h3>自动销毁</h3>
<p>达到次数自动删除</p>
</div>
</div>
</section>
</main>
<footer class="app-footer">
<p>© <?= date('Y') ?> 阅后自焚图片分享系统 | 所有文件将在达到访问次数后自动销毁</p>
</footer>
</div>
<script>
// 计数器功能
const minusBtn = document.querySelector('.minus');
const plusBtn = document.querySelector('.plus');
const viewsInput = document.getElementById('views');
minusBtn.addEventListener('click', function() {
let value = parseInt(viewsInput.value) || 1;
if (value > 1) {
viewsInput.value = value - 1;
}
});
plusBtn.addEventListener('click', function() {
let value = parseInt(viewsInput.value) || 1;
if (value < 999) {
viewsInput.value = value + 1;
}
});
// 文件上传区域交互
const fileInput = document.getElementById('file');
const fileInputArea = document.getElementById('file-input-area');
fileInput.addEventListener('change', function() {
if (this.files.length > 0) {
const fileName = this.files[0].name.length > 20
? this.files[0].name.substring(0, 17) + '...'
: this.files[0].name;
fileInputArea.innerHTML = `
<i class="fas fa-check-circle" style="color: var(--success-color);"></i>
<p>${fileName}</p>
<span class="btn">重新选择</span>
`;
fileInputArea.style.borderColor = 'var(--success-color)';
fileInputArea.style.backgroundColor = '#f0fff4';
// 重新添加文件输入
const newInput = document.createElement('input');
newInput.type = 'file';
newInput.name = 'file';
newInput.id = 'file';
newInput.required = true;
newInput.accept = 'image/*';
newInput.style.position = 'absolute';
newInput.style.top = '0';
newInput.style.left = '0';
newInput.style.width = '100%';
newInput.style.height = '100%';
newInput.style.opacity = '0';
newInput.style.cursor = 'pointer';
fileInputArea.appendChild(newInput);
newInput.addEventListener('change', fileInput.onchange);
}
});
// 拖拽上传功能
fileInputArea.addEventListener('dragover', (e) => {
e.preventDefault();
fileInputArea.style.borderColor = 'var(--primary-color)';
fileInputArea.style.backgroundColor = '#edf2f7';
});
fileInputArea.addEventListener('dragleave', () => {
fileInputArea.style.borderColor = 'var(--border-color)';
fileInputArea.style.backgroundColor = '#f8fafc';
});
fileInputArea.addEventListener('drop', (e) => {
e.preventDefault();
fileInputArea.style.borderColor = 'var(--border-color)';
fileInputArea.style.backgroundColor = '#f8fafc';
if (e.dataTransfer.files.length) {
fileInput.files = e.dataTransfer.files;
const event = new Event('change');
fileInput.dispatchEvent(event);
}
});
// 复制链接功能
const copyBtn = document.getElementById('copy-btn');
if (copyBtn) {
copyBtn.addEventListener('click', function() {
const linkInput = document.getElementById('generated-link');
linkInput.select();
document.execCommand('copy');
const originalText = copyBtn.textContent;
copyBtn.textContent = '已复制!';
copyBtn.style.background = 'var(--success-color)';
setTimeout(() => {
copyBtn.textContent = originalText;
copyBtn.style.background = 'var(--primary-color)';
}, 2000);
});
}
// 如果有链接生成,滚动到结果区域
<?php if (!empty($link)): ?>
setTimeout(() => {
document.querySelector('.result-section').scrollIntoView({
behavior: 'smooth'
});
}, 300);
<?php endif; ?>
</script>
</body>
</html>
感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
暂无评论内容