文件托管到哪儿了?
Closed this issue · 9 comments
SokWith commented
文件上传后,如何查看历史文件呢?
拜托详细一点点的说明一下。
SokWith commented
看上去还不支持,close
SokWith commented
cf-pages/Telegraph-Image#116 (comment)
类似项目有后台功能
要是能扩充后台功能成一个图库站点就更好了。
SokWith commented
https://upimg.wook.eu.org/
简单改了一个使用本地存储历史记录的
index.html:
<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Telegraph Image Hosting</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.5.3/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div class="full-window" ondragover="event.preventDefault()">
<div class="container card">
<h3 class="text-center">Telegraph Image Hosting</h3>
<p class="text-center text-muted">Free & Unlimited Image Hosting</p>
<button
id="upload"
class="btn btn-primary mx-auto"
type="button"
title="Supported formats: Images, videos, GIFs"
>
<span class="spinner-grow spinner-grow-sm d-none"></span>
<span class="upload-text"
>Drag & Drop your files or <u><i>Browse</i></u></span
>
<input
id="fileInput"
type="file"
name="file"
accept="image/*, video/*"
/>
</button>
<div
id="uploadStatus"
class="text-center"
style="margin-top: 10px"
></div>
<a
class="text-center text-muted"
href="https://github.com/ifyour/cf-image-hosting"
target="_blank"
>GitHub</a
>
</div>
</div>
<input type="text" id="usernameInput" placeholder="Enter Category Tags" style="position: absolute; top: 10px; right: 100px;">
<button id="listImagesButton" style="position: absolute; top: 10px; right: 10px;">列出记录</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/browser-image-compression/2.0.2/browser-image-compression.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
script.js
const fileInput = document.getElementById("fileInput");
const uploadStatus = document.getElementById("uploadStatus");
const fullWindow = document.querySelector(".full-window");
document.addEventListener("paste", onFilePaste);
fullWindow.addEventListener("drop", onFileDrop);
fileInput.addEventListener("change", onFileChange);
// 列出按钮执行动作后,在页面中添加一个输出框显示结果
document.getElementById('listImagesButton').addEventListener('click', () => {
const username = document.getElementById('usernameInput').value;
const savedValues = localStorage.getItem(username);
const outputDiv = document.createElement('div');
outputDiv.innerHTML = `<h4>${username}'s Saved Images:</h4>`;
// 创建一个文本区域元素以显示图片URL
const textarea = document.createElement('textarea');
textarea.rows = 5; // 可以根据需要调整行数
textarea.cols = 60; // 可以根据需要调整列数
// 将文本区域添加到outputDiv的顶部
outputDiv.appendChild(textarea);
if (savedValues) {
const images = savedValues.split(';').filter(Boolean);
images.forEach(src => {
// 将图片URL添加到文本区域,并确保使用正确的换行符
textarea.value += src + '\n'; // 这里使用 '\n' 来换行
});
images.forEach((src, index) => {
const imgElement = document.createElement('img');
imgElement.src = src;
imgElement.style.maxWidth = '200px';
// 将图片元素添加到文本区域下方
outputDiv.appendChild(imgElement);
});
} else {
outputDiv.innerHTML += `<p>No images saved for ${username}</p>`;
}
document.body.prepend(outputDiv);
});
function onFileChange() {
const file = fileInput.files[0];
if (file) handleUpload(file);
}
function onFileDrop(event) {
event.preventDefault();
let files = event.dataTransfer.files;
for (let i = 0; i < files.length; i++) {
handleUpload(files[i]);
}
}
function onFilePaste(event) {
const items = (event.clipboardData || event.originalEvent.clipboardData)
.items;
for (let index in items) {
const item = items[index];
if (item.kind === "file") {
const blob = item.getAsFile();
const reader = new FileReader();
reader.onload = (event) => {
const base64Data = event.target.result.split(",")[1];
const dataType = event.target.result.split(";")[0];
const fileType = dataType.split(":")[1];
const data = window.atob(base64Data);
const ia = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i);
}
const blob = new Blob([ia.buffer], { type: fileType });
const file = new File([blob], "screenshot.jpg", { type: fileType });
handleUpload(file);
};
reader.readAsDataURL(blob);
}
}
}
function onFileUrlCopy() {
const imageUrl = document.getElementById("imageUrl");
navigator.clipboard
.writeText(imageUrl.value)
.then(() => {
document.querySelector(".copy-btn").textContent = "Copied ✨";
setTimeout(() => {
document.querySelector(".copy-btn").textContent = "Copy";
}, 1000);
})
.catch((error) => {
console.error("Failed to copy URL", error);
});
}
function handleCompressFile(file) {
const maxFileSize = 5 * 1024 * 1024; // 5MB
return new Promise((resolve) => {
if (file.size <= maxFileSize || !file.type.startsWith("image")) {
resolve(file);
} else {
imageCompression(file, { maxSizeMB: 5 })
.then((compressedFile) => {
resolve(compressedFile);
})
.catch((error) => {
console.error(">> imageCompression error", error);
resolve(file);
});
}
});
}
function handleUpload(file) {
document.querySelector(".upload-text").textContent = "Uploading...";
document.querySelector(".spinner-grow").classList.remove("d-none");
handleCompressFile(file).then((compressedFile) => {
const formData = new FormData();
formData.append("file", compressedFile);
fetch("/upload", { method: "POST", body: formData })
.then((response) => response.json())
.then((data) => {
if (data && data.error) {
throw new Error(data.error);
}
const src = window.location.origin + data[0].src;
const newSrc = src.replace(window.location.origin, 'https://imghost.wook.eu.org');
fetch(newSrc)
.then((response) => {
// 处理后台访问链接的逻辑
})
.catch((error) => {
console.error("Failed to access the modified URL", error);
});
uploadStatus.innerHTML = `
<div class="alert alert-success text-center">Successful 🥳</div>
<div class="input-group" style="margin-bottom: 10px">
<input type="text" class="form-control" id="imageUrl" value="${src}">
<div class="input-group-append">
<button class="btn btn-outline-secondary copy-btn" type="button">Copy</button>
<button id="saveButton" class="btn btn-primary">Save</button>
</div>
</div>
${
file.type.startsWith("video")
? `<video src="${src}" class="img-fluid mb-3" controls></video>`
: `<img src="${src}" class="img-fluid mb-3" alt="Uploaded Image">`
}
`;
// 保存按钮执行保存动作
document.getElementById('saveButton').addEventListener('click', () => {
const username = document.getElementById('usernameInput').value;
const src = document.getElementById('imageUrl').value;
const existingValue = localStorage.getItem(username) || '';
localStorage.setItem(username, existingValue + src + ';');
});
document
.querySelector(".copy-btn")
.addEventListener("click", onFileUrlCopy);
})
.catch((error) => {
uploadStatus.innerHTML = `
<div class="alert alert-danger">${
error || "Upload failed. Please try again."
}</div>
`;
})
.finally(() => {
document.querySelector(".upload-text").textContent = "Upload Again";
document.querySelector(".spinner-grow").classList.add("d-none");
});
});
}
增加了历史URL地址输出,便于复制保存。
ifyour commented
抱歉,最近有点忙,没时间搞,你可以 fork 一份部署 👍🏻
SokWith commented
<?php
session_start(); // 开始会话
$albumDir = 'albums/';
$albums = glob($albumDir . '*.txt');
$correctPassword = 'addroot'; // 设置固定的口令
// 处理备份相册的操作
if (isset($_POST['backup']) && isset($_SESSION['password']) && $_SESSION['password'] === $correctPassword) {
$zip = new ZipArchive();
$backupFileName = $albumDir . 'backup_' . date('YmdHis') . '.zip';
if ($zip->open($backupFileName, ZipArchive::CREATE) === TRUE) {
foreach ($albums as $album) {
$zip->addFile($album, basename($album));
}
$zip->close();
// 触发下载
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($backupFileName) . '"');
header('Content-Length: ' . filesize($backupFileName));
ob_clean(); // 清除缓冲区
flush(); // 刷新输出缓冲
readfile($backupFileName);
// 删除服务器上的备份文件
unlink($backupFileName);
exit;
} else {
echo "<p>备份失败。</p>";
}
}
// 检查会话中的口令或表单提交的口令
if (isset($_SESSION['password']) && $_SESSION['password'] === $correctPassword) {
// 口令正确,显示管理界面
// 显示备份按钮和返回首页按钮
echo "<div style='display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px;'>";
echo "<a href='index.php' style='text-decoration: none;'>";
echo "<button type='button'>返回首页</button>";
echo "</a>";
echo "<form method='post'>";
echo "<input type='submit' name='backup' value='备份相册'>";
echo "</form>";
echo "</div>";
// 处理创建新相册的操作
if (isset($_POST['create']) && !empty($_POST['newAlbumName'])) {
$newAlbumName = trim($_POST['newAlbumName']);
$newAlbumFile = $albumDir . $newAlbumName . '.txt';
if (!file_exists($newAlbumFile)) {
file_put_contents($newAlbumFile, '');
echo "<p>新相册 '{$newAlbumName}' 创建成功。</p>";
} else {
echo "<p>相册 '{$newAlbumName}' 已存在。</p>";
}
}
// 如果设置了album参数,显示相册内容管理界面
if (isset($_GET['album'])) {
$albumName = basename($_GET['album'], '.txt');
$albumFile = $albumDir . $albumName . '.txt';
// 显示相册内容管理界面
echo "<h2>管理相册: $albumName</h2>";
echo "<a href='?'>返回相册列表</a><br>";
// 处理增加图片的操作
if (isset($_POST['add'])) {
$imageUrls = explode("\n", $_POST['imageUrls']); // 从文本区域获取多个URL
foreach ($imageUrls as $imageUrl) {
if (!empty($imageUrl)) {
file_put_contents($albumFile, trim($imageUrl) . "\n", FILE_APPEND);
}
}
}
// 处理删除图片的操作
if (isset($_POST['delete'])) {
$imageUrl = $_POST['imageUrl'];
$images = file($albumFile, FILE_IGNORE_NEW_LINES);
$images = array_filter($images, function ($line) use ($imageUrl) {
return trim($line) !== trim($imageUrl);
});
file_put_contents($albumFile, implode("\n", $images) . "\n");
}
// 显示图片和删除按钮
$images = file($albumFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
echo "<div style='display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;'>";
foreach ($images as $imageUrl) {
echo "<div style='text-align: center;'>";
echo "<a href='$imageUrl'><img src='$imageUrl' alt='Thumbnail' width='100' height='100'></a>";
echo "<form method='post' style='display: inline;' onsubmit='return confirmDelete();'>";
echo "<input type='hidden' name='imageUrl' value='$imageUrl'>";
echo "<input type='submit' name='delete' value='删除'>";
echo "</form>";
echo "</div>";
}
echo "</div>";
// 显示添加图片表单
echo "<form method='post' style='margin-top: 20px;'>";
echo "<textarea name='imageUrls' placeholder='输入图片URL,每行一个' style='width: 500px; height: 100px;'></textarea>";
echo "<input type='submit' name='add' value='批量添加图片'>";
echo "</form>";
} else {
// 显示相册列表
echo "<h2>相册列表</h2>";
echo "<div style='display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;'>";
foreach ($albums as $album) {
$albumName = basename($album, '.txt');
echo "<a href='?album=$albumName' style='text-align: center;'>$albumName</a>";
}
echo "</div>";
// 显示创建新相册表单
echo "<form method='post' style='margin-top: 20px;'>";
echo "<input type='text' name='newAlbumName' placeholder='输入新相册名称'>";
echo "<input type='submit' name='create' value='创建新相册'>";
echo "</form>";
}
} elseif (isset($_POST['password']) && $_POST['password'] === $correctPassword) {
// 口令正确,保存口令到会话
$_SESSION['password'] = $_POST['password'];
// 重定向到相同页面,避免表单重复提交
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
} else {
// 显示口令输入表单
echo "<form method='post'>";
echo "<input type='password' name='password' placeholder='输入口令'>";
echo "<input type='submit' value='提交'>";
echo "</form>";
}
?>
<script>
// JavaScript函数用于在删除操作前确认
function confirmDelete() {
return confirm('确定要删除这张图片吗?');
}
</script>
<!-- HTML 内容 -->
</body>
</html>
ifyour commented
换到 pages 部署了,已支持历史上传记录。🤪
SokWith commented
换到 pages 部署了,已支持历史上传记录。🤪
代码没提交更新吗?
其实打算在上面相册管理站点增加一个图片上传功能,调用这个项目的API,我代码小白,不知道这个功能该如何向AI描述让AI来完善上面站点代码。
功能就是:点击批量增加图片,如果输入框中没有URL地址,则打开文件管理器,选择图片(可以多选),调用API上传,接收上传返回的URL地址(多选需要保留全部),代替文本框的输入的值,完成批量图片增加。