Publish #1
+8
-2
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Аналог DropMeFiles</title>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="uploadPage">
|
||||
@@ -34,6 +34,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="status" id="status"></div>
|
||||
<div id="uploadProgress" class="download-progress" style="display: none;">
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar" id="uploadProgressBar"></div>
|
||||
</div>
|
||||
<p class="progress-text" id="uploadProgressText">0%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,6 +60,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/script.js"></script>
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+45
-8
@@ -366,10 +366,17 @@ function initUploadPage() {
|
||||
uploadData.fields["key"] = fileUuid;
|
||||
delete uploadData.fields["Content-Type"];
|
||||
|
||||
setStatus('Загрузка файла на сервер...', '');
|
||||
// Hide status, show progress bar
|
||||
statusDiv.style.display = 'none';
|
||||
const uploadProgress = document.getElementById('uploadProgress');
|
||||
const uploadProgressBar = document.getElementById('uploadProgressBar');
|
||||
const uploadProgressText = document.getElementById('uploadProgressText');
|
||||
uploadProgress.style.display = 'block';
|
||||
uploadProgressBar.style.width = '0%';
|
||||
uploadProgressText.textContent = '0%';
|
||||
|
||||
// Step 2: Upload to S3 using form-data
|
||||
// Add all fields from the API response (order matters for S3, file should be last)
|
||||
// Step 2: Upload to S3 using XMLHttpRequest for progress tracking
|
||||
await new Promise((resolve, reject) => {
|
||||
const formData = new FormData();
|
||||
Object.keys(uploadData.fields).forEach(key => {
|
||||
formData.append(key, uploadData.fields[key]);
|
||||
@@ -377,14 +384,39 @@ function initUploadPage() {
|
||||
// File must be appended last
|
||||
formData.append('file', file);
|
||||
|
||||
const uploadResponse = await fetch(uploadData.url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
// Track upload progress
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
const percent = Math.round((event.loaded / event.total) * 100);
|
||||
uploadProgressBar.style.width = percent + '%';
|
||||
uploadProgressText.textContent = `${percent}% (${formatBytes(event.loaded)} / ${formatBytes(event.total)})`;
|
||||
}
|
||||
});
|
||||
|
||||
if (!uploadResponse.ok) {
|
||||
throw new Error('Ошибка при загрузке файла на сервер');
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Ошибка загрузки: ${xhr.status}`));
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
reject(new Error('Ошибка при загрузке файла на сервер'));
|
||||
});
|
||||
|
||||
xhr.addEventListener('abort', () => {
|
||||
reject(new Error('Загрузка прервана'));
|
||||
});
|
||||
|
||||
xhr.open('POST', uploadData.url);
|
||||
xhr.send(formData);
|
||||
});
|
||||
|
||||
// Hide progress bar after successful upload
|
||||
uploadProgress.style.display = 'none';
|
||||
|
||||
// Success!
|
||||
const downloadUrl = `${window.location.origin}/get/${fileUuid}`;
|
||||
@@ -405,6 +437,11 @@ function initUploadPage() {
|
||||
}
|
||||
showErrorPopup(errorMessage);
|
||||
setStatus('', '');
|
||||
// Hide progress bar on error
|
||||
const uploadProgress = document.getElementById('uploadProgress');
|
||||
if (uploadProgress) {
|
||||
uploadProgress.style.display = 'none';
|
||||
}
|
||||
} finally {
|
||||
uploadButton.disabled = false;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@ body {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
padding: 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.page-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -30,6 +37,13 @@ h1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
h1 {
|
||||
font-size: clamp(24px, 6vw, 32px);
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
width: min(640px, 100%);
|
||||
background: #ffffffdd;
|
||||
@@ -42,6 +56,14 @@ h1 {
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.upload-container {
|
||||
padding: 20px;
|
||||
gap: 16px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropzone {
|
||||
border: 2px dashed #6366f1;
|
||||
border-radius: 16px;
|
||||
@@ -55,6 +77,13 @@ h1 {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dropzone {
|
||||
padding: 32px 16px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropzone:focus,
|
||||
.dropzone:focus-within {
|
||||
outline: none;
|
||||
@@ -130,6 +159,17 @@ button {
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
touch-action: manipulation;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
button {
|
||||
padding: 16px 24px;
|
||||
font-size: 16px;
|
||||
min-height: 48px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
button:hover:not(:disabled) {
|
||||
@@ -204,6 +244,16 @@ button:disabled {
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
font-family: inherit;
|
||||
touch-action: manipulation;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.download-button {
|
||||
padding: 16px 24px;
|
||||
width: 100%;
|
||||
min-height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.download-button:hover {
|
||||
@@ -246,6 +296,53 @@ button:disabled {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.error-popup {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
transform: none;
|
||||
max-width: none;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status.error {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.file-info h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropzone p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropzone p.strong {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success content */
|
||||
.success-content {
|
||||
animation: fadeIn 0.3s ease-in;
|
||||
@@ -282,6 +379,15 @@ button:disabled {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.download-link-input {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
padding: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.download-link-input:focus {
|
||||
outline: none;
|
||||
border-color: #6366f1;
|
||||
@@ -299,6 +405,16 @@ button:disabled {
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
white-space: nowrap;
|
||||
touch-action: manipulation;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.copy-link-button {
|
||||
width: 100%;
|
||||
padding: 14px 24px;
|
||||
min-height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.copy-link-button:hover {
|
||||
@@ -325,6 +441,16 @@ button:disabled {
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
touch-action: manipulation;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.upload-another-button {
|
||||
width: 100%;
|
||||
padding: 14px 24px;
|
||||
min-height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-another-button:hover {
|
||||
@@ -363,3 +489,82 @@ button:disabled {
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.status {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status.error {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.file-info h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropzone p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropzone p.strong {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.error-popup {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
transform: none;
|
||||
max-width: none;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
body {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
padding: 16px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.dropzone {
|
||||
padding: 24px 12px;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user