Файл отправляется, даже появляется на файлообменнике, но в ответ приходит ошибка получения POST
делаю сайт, в котором можно будет обмениваться модами, сейчас работаю над тем, чтобы файл посылался на файлообменник, а оттуда приходил его id и вместе с другими данными отправлялся, остановился на том, что уже 3 дня пытаюсь решить проблему, как я понимаю CORS, то есть, файл отправляется, даже появляется на файлообменнике, но в ответ приходит ошибка получения POST. Сам CORS реагирует ТОЛЬКО на архив, что я отправляю на TransferNow.
Если я правильно все понял, то проблема с тем, как я настроил сервер, но что бы я не читал, что бы не предпринимал, ошибка не уходит. Сама ошибка:
XHR не удалось загрузить: POST " http://localhost:3000/proxy/upload
uploadToTransferNow @ Upload.js:100
Выполнен переход к ...
Вот что пишет во вкладке сети в браузере:
URL-адрес запроса:
http://localhost:3000/proxy/upload
Политика источника ссылки:
strict-origin-when-cross-origin
accept:
*/*
accept-encoding:
gzip, deflate, br, zstd
accept-language:
ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7,uk;q=0.6
connection:
keep-alive
content-length:
459382
content-type:
multipart/form-data; boundary=----WebKitFormBoundaryjAQljaDPreQcoyRb
host:
localhost:3000
origin:
http://192.168.1.143:5500
referer:
http://192.168.1.143:5500/
sec-ch-ua:
"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"Windows"
sec-fetch-dest:
empty
sec-fetch-mode:
cors
sec-fetch-site:
cross-site
user-agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
Вот код Upload.js
document.addEventListener('DOMContentLoaded', () => {
const uploadForm = document.getElementById('upload-form');
const logoInput = document.getElementById('logo');
const modFileInput = document.getElementById('mod-file');
const screenshotsInput = document.getElementById('screenshots');
const logoContainer = document.getElementById('logo-container');
const screenshotsContainer = document.getElementById('screenshots-container');
const logoProgress = document.getElementById('logo-progress');
const screenshotsProgress = document.getElementById('screenshots-progress');
const logoThumbnails = document.getElementById('logo-thumbnails');
const screenshotsThumbnails = document.getElementById('screenshots-thumbnails');
let screenshotsUrls = [];
let deleteHashes = [];
function handleDragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy'; // Указываем, что перетаскиваемый объект будет скопирован
event.currentTarget.classList.add('drag-over');
console.log('Drag over');
}
function handleDragLeave(event) {
event.currentTarget.classList.remove('drag-over');
console.log('Drag leave');
}
function handleDrop(event, inputElement, maxFiles) {
event.preventDefault();
event.currentTarget.classList.remove('drag-over');
if (event.dataTransfer.files.length > maxFiles) {
alert(`Можно загрузить не более ${maxFiles} файлов.`);
return;
}
inputElement.files = event.dataTransfer.files;
event.currentTarget.classList.add('has-file');
console.log('Files dropped');
handleFileUpload(inputElement, event.currentTarget.querySelector('.progress-bar'), event.currentTarget.querySelector('.thumbnails'));
}
async function handleFileUpload(inputElement, progressBar, thumbnailsContainer) {
const files = inputElement.files;
if (thumbnailsContainer) {
thumbnailsContainer.innerHTML = '';
Array.from(files).forEach(file => {
const reader = new FileReader();
reader.onload = (e) => {
const img = document.createElement('img');
img.src = e.target.result;
thumbnailsContainer.appendChild(img);
};
reader.readAsDataURL(file);
});
}
progressBar.style.width = '100%';
setTimeout(() => {
progressBar.style.width = '0%';
}, 500);
console.log('File uploaded');
}
[logoContainer, screenshotsContainer].forEach(container => {
const maxFiles = container === screenshotsContainer ? 3 : 1;
container.addEventListener('dragover', handleDragOver);
container.addEventListener('dragleave', handleDragLeave);
container.addEventListener('drop', (event) => handleDrop(event, container.querySelector('input[type="file"]'), maxFiles));
});
logoInput.addEventListener('change', () => {
if (logoInput.files.length > 1) {
alert('Можно загрузить только один логотип.');
logoInput.value = '';
return;
}
handleFileUpload(logoInput, logoProgress, logoThumbnails);
});
screenshotsInput.addEventListener('change', () => {
if (screenshotsInput.files.length > 3) {
alert('Можно загрузить не более 3 скриншотов.');
screenshotsInput.value = '';
return;
}
handleFileUpload(screenshotsInput, screenshotsProgress, screenshotsThumbnails);
});
modFileInput.addEventListener('change', () => {
if (modFileInput.files.length > 1) {
alert('Можно загрузить только один файл мода.');
modFileInput.value = '';
return;
}
console.log('Файл мода выбран:', modFileInput.files[0]);
});
async function uploadToTransferNow(file) {
console.log('Начало загрузки на TransferNow');
const formData = new FormData();
formData.append('file', file);
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/proxy/upload'); // Используем прокси-сервер
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100;
console.log(`Upload progress: ${percentComplete}%`);
}
};
xhr.onload = () => {
if (xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
console.log('Загрузка на TransferNow завершена успешно:', response);
resolve(response.transferLink);
} else {
console.error('Ошибка загрузки на TransferNow:', xhr.statusText);
reject(new Error(`Ошибка загрузки на TransferNow: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
console.error('Ошибка сети при загрузке на TransferNow');
reject(new Error('Ошибка сети'));
};
xhr.send(formData);
console.log('Запрос на загрузку отправлен');
});
}
async function uploadToImgur(file, progressBar) {
console.log('Начало загрузки на Imgur');
const formData = new FormData();
formData.append('image', file);
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.imgur.com/3/image');
xhr.setRequestHeader('Authorization', 'Client-ID a7e1b05ddeeed49');
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100;
progressBar.style.width = `${percentComplete}%`;
console.log(`Upload progress: ${percentComplete}%`);
}
};
xhr.onload = () => {
if (xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
console.log('Загрузка на Imgur завершена успешно:', response);
resolve(response.data.link);
} else {
console.error('Ошибка загрузки на Imgur:', xhr.statusText);
reject(new Error(`Ошибка загрузки на Imgur: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
console.error('Ошибка сети при загрузке на Imgur');
reject(new Error('Ошибка сети'));
};
xhr.send(formData);
console.log('Запрос на загрузку отправлен');
});
}
async function uploadToImgurWithRetry(file, progressBar, retries = 5) {
try {
return await uploadToImgur(file, progressBar);
} catch (error) {
if (retries > 0) {
console.warn(`Ошибка загрузки на Imgur, повторная попытка... (${retries})`);
return await uploadToImgurWithRetry(file, progressBar, retries - 1);
} else {
throw error;
}
}
}
async function deleteFromImgur(deletehash) {
console.log('Начало удаления с Imgur');
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('DELETE', `https://api.imgur.com/3/image/${deletehash}`);
xhr.setRequestHeader('Authorization', 'Client-ID ###');
xhr.onload = () => {
if (xhr.status === 200) {
console.log('Удаление с Imgur завершено успешно');
resolve();
} else {
console.error('Ошибка удаления с Imgur:', xhr.statusText);
reject(new Error(`Ошибка удаления с Imgur: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
console.error('Ошибка сети при удалении с Imgur');
reject(new Error('Ошибка сети'));
};
xhr.send();
console.log('Запрос на удаление отправлен');
});
}
uploadForm.addEventListener('submit', async (event) => {
event.preventDefault();
event.stopPropagation();
console.log('Форма отправлена');
const formData = new FormData(uploadForm);
const logoFile = formData.get('logo');
const modFile = formData.get('mod-file');
if (!logoFile || !modFile) {
console.error('Файл не был загружен');
alert('Пожалуйста, загрузите файл перед отправкой формы.');
return;
}
try {
console.log('Загрузка логотипа на Imgur');
const logoUrl = await uploadToImgurWithRetry(logoFile, logoProgress);
console.log('Логотип загружен:', logoUrl);
console.log('Загрузка мод-файла на TransferNow');
const modFileUrl = await uploadToTransferNow(modFile);
console.log('Мод-файл загружен:', modFileUrl);
const modData = {
name: formData.get('name'),
description: formData.get('description').replace(/\n/g, '<br>'), // Сохранение переносов строк
short_description: formData.get('opis'), // Извлечение short_description из инпута "opis"
game: formData.get('game'),
logo_url: logoUrl,
screenshots: screenshotsUrls,
mod_file_url: modFileUrl
};
console.log('Данные для отправки на сервер:', modData);
console.log('Отправка данных на сервер');
const response = await fetch('http://localhost:3000/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(modData),
});
const result = await response.json();
if (response.ok) {
console.log('Мод успешно загружен:', result);
alert('Мод успішно завантажено!');
} else {
console.error('Ошибка при загрузке мода:', result.error);
alert(result.error || 'Щось пішло не так');
}
} catch (error) {
console.error('Ошибка на сервере:', error);
alert('Помилка на сервері');
}
});
});
Так же вот код index.js, через который проходит отправка архива на файлообменни:
const express = require('express');
const { Pool } = require('pg');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');
const cors = require('cors'); // Импортируем пакет cors
const multer = require('multer'); // Импортируем multer для обработки загрузки файлов
const { upload } = require('@transfernow/api-sdk'); // Импортируем библиотеку TransferNow
const path = require('path'); // Импортируем path для работы с путями файлов
// Настройка Express
const app = express();
app.use(bodyParser.json()); // Для обработки JSON в теле запроса
app.use(cors()); // Используем cors middleware
const pool = new Pool({
user: 'postgres', // Замените на имя вашего пользователя БД
host: 'localhost',
database: 'Users', // Замените на имя вашей базы данных
password: '1012', // Замените на пароль вашей базы данных
port: 5432,
});
// Настройка multer для обработки загрузки файлов
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/');
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname);
}
});
const uploadMiddleware = multer({ storage: storage });
// Обработчик для корневого URL
app.get('/', (req, res) => {
res.send('Сервер работает!');
});
// Обработка загрузки мода
app.post('/upload', async (req, res) => {
const { name, description, short_description, game, logo_url, screenshots, mod_file_url } = req.body;
console.log('Полученные данные для загрузки мода:', req.body);
try {
const tableName = `public."${game}_Mods"`;
const result = await pool.query(
`INSERT INTO ${tableName} (name, description, short_description, logo_url, screenshots, mod_file_url) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`,
[name, description, short_description, logo_url, JSON.stringify(screenshots), mod_file_url]
);
console.log('Мод успешно загружен:', result.rows[0]);
res.status(201).json(result.rows[0]);
} catch (error) {
console.error('Ошибка на сервере:', error);
res.status(500).json({ error: 'Помилка на сервері' });
}
});
// Прокси для загрузки на TransferNow
app.post('/proxy/upload', uploadMiddleware.single('file'), async (req, res) => {
try {
if (!req.file) {
throw new Error('Файл не был загружен');
}
console.log('Загруженный файл:', req.file);
const response = await upload({
apiKey: '###',
toEmails: ['[email protected]'],
filePaths: [req.file.path],
message: 'File upload via proxy',
subject: 'File Upload'
});
const transferLink = `https://www.transfernow.net/dl/${response.transferId}`;
console.log(`Transfer ${response.transferId} was sent successfully`);
console.log(`Transfer link: ${transferLink}`);
// Отправляем ссылку обратно клиенту
res.json({ transferLink });
} catch (error) {
console.error('Ошибка при загрузке на TransferNow:', error.message);
res.status(500).json({ error: 'Ошибка при загрузке на TransferNow' });
}
});
// Запуск сервера
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Ответы (1 шт):
Современные браузеры стремятся запретить получать или отправлять данные из сторонних источников в обход пользователя.
Попробуйте генерировать кнопку с адресом скачивания. По нажатию на кнопку файл должен скачаться локально и только после этого его можно будет обработать.
Другой вариант - отдайте пользователю ссылку на файлообменник, а файл, если его нужно показать тут же, отправьте через свой сервер.