Update server.js
Browse files
server.js
CHANGED
|
@@ -3,7 +3,7 @@ const axios = require("axios");
|
|
| 3 |
const fs = require("fs");
|
| 4 |
const path = require("path");
|
| 5 |
const https = require("https");
|
| 6 |
-
const crypto = require("crypto");
|
| 7 |
|
| 8 |
const app = express();
|
| 9 |
const PORT = 7860;
|
|
@@ -17,7 +17,7 @@ if (!fs.existsSync(DOWNLOAD_DIR)) {
|
|
| 17 |
// Axios instance to ignore SSL verification
|
| 18 |
const axiosInstance = axios.create({
|
| 19 |
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
|
| 20 |
-
timeout: 300000 // 5 minutes timeout
|
| 21 |
});
|
| 22 |
|
| 23 |
// Function to generate a unique request ID
|
|
@@ -44,6 +44,56 @@ const scheduleFileDeletion = (filePath, delay = 600000) => {
|
|
| 44 |
}, delay);
|
| 45 |
};
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
// **API Route - Responds Immediately, Processes in Background**
|
| 48 |
app.get("/download", async (req, res) => {
|
| 49 |
const fileUrl = req.query.url;
|
|
@@ -70,31 +120,9 @@ app.get("/download", async (req, res) => {
|
|
| 70 |
|
| 71 |
// **Background Processing (Download)**
|
| 72 |
(async () => {
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
const response = await axiosInstance({
|
| 77 |
-
url: fileUrl,
|
| 78 |
-
method: "GET",
|
| 79 |
-
responseType: "stream",
|
| 80 |
-
headers: { "User-Agent": "Mozilla/5.0", "Accept": "*/*" }
|
| 81 |
-
});
|
| 82 |
-
|
| 83 |
-
const writer = fs.createWriteStream(filePath);
|
| 84 |
-
response.data.pipe(writer);
|
| 85 |
-
|
| 86 |
-
await new Promise((resolve, reject) => {
|
| 87 |
-
writer.on("finish", resolve);
|
| 88 |
-
writer.on("error", reject);
|
| 89 |
-
});
|
| 90 |
-
|
| 91 |
-
console.log(`✅ [${requestId}] Download complete: ${filePath}`);
|
| 92 |
-
|
| 93 |
-
// Schedule deletion
|
| 94 |
scheduleFileDeletion(filePath);
|
| 95 |
-
|
| 96 |
-
} catch (error) {
|
| 97 |
-
console.error(`❌ [${requestId}] Processing error:`, error.message);
|
| 98 |
}
|
| 99 |
})();
|
| 100 |
});
|
|
|
|
| 3 |
const fs = require("fs");
|
| 4 |
const path = require("path");
|
| 5 |
const https = require("https");
|
| 6 |
+
const crypto = require("crypto");
|
| 7 |
|
| 8 |
const app = express();
|
| 9 |
const PORT = 7860;
|
|
|
|
| 17 |
// Axios instance to ignore SSL verification
|
| 18 |
const axiosInstance = axios.create({
|
| 19 |
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
|
| 20 |
+
timeout: 300000, // 5 minutes timeout
|
| 21 |
});
|
| 22 |
|
| 23 |
// Function to generate a unique request ID
|
|
|
|
| 44 |
}, delay);
|
| 45 |
};
|
| 46 |
|
| 47 |
+
// **Download Function with Integrity Check**
|
| 48 |
+
const downloadFile = async (fileUrl, filePath, requestId) => {
|
| 49 |
+
let retries = 3; // Retry up to 3 times
|
| 50 |
+
|
| 51 |
+
while (retries > 0) {
|
| 52 |
+
try {
|
| 53 |
+
console.log(`⬇️ [${requestId}] Downloading: ${fileUrl}`);
|
| 54 |
+
|
| 55 |
+
const response = await axiosInstance({
|
| 56 |
+
url: fileUrl,
|
| 57 |
+
method: "GET",
|
| 58 |
+
responseType: "stream",
|
| 59 |
+
headers: { "User-Agent": "Mozilla/5.0", "Accept": "*/*" }
|
| 60 |
+
});
|
| 61 |
+
|
| 62 |
+
const totalSize = response.headers["content-length"]; // Get file size
|
| 63 |
+
console.log(`📏 [${requestId}] Expected size: ${totalSize} bytes`);
|
| 64 |
+
|
| 65 |
+
const writer = fs.createWriteStream(filePath);
|
| 66 |
+
response.data.pipe(writer);
|
| 67 |
+
|
| 68 |
+
await new Promise((resolve, reject) => {
|
| 69 |
+
writer.on("finish", resolve);
|
| 70 |
+
writer.on("error", reject);
|
| 71 |
+
});
|
| 72 |
+
|
| 73 |
+
// Verify file size
|
| 74 |
+
const fileSize = fs.statSync(filePath).size;
|
| 75 |
+
if (totalSize && fileSize < totalSize * 0.9) { // Allow minor variance
|
| 76 |
+
console.error(`⚠️ [${requestId}] Download incomplete: ${fileSize} bytes (expected ${totalSize} bytes)`);
|
| 77 |
+
fs.unlinkSync(filePath);
|
| 78 |
+
throw new Error("Incomplete download, retrying...");
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
console.log(`✅ [${requestId}] Download complete: ${filePath}`);
|
| 82 |
+
return true;
|
| 83 |
+
|
| 84 |
+
} catch (error) {
|
| 85 |
+
console.error(`❌ [${requestId}] Download failed: ${error.message}`);
|
| 86 |
+
retries--;
|
| 87 |
+
|
| 88 |
+
if (retries === 0) {
|
| 89 |
+
console.error(`⛔ [${requestId}] All retries failed, skipping.`);
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
return false;
|
| 95 |
+
};
|
| 96 |
+
|
| 97 |
// **API Route - Responds Immediately, Processes in Background**
|
| 98 |
app.get("/download", async (req, res) => {
|
| 99 |
const fileUrl = req.query.url;
|
|
|
|
| 120 |
|
| 121 |
// **Background Processing (Download)**
|
| 122 |
(async () => {
|
| 123 |
+
const success = await downloadFile(fileUrl, filePath, requestId);
|
| 124 |
+
if (success) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
scheduleFileDeletion(filePath);
|
|
|
|
|
|
|
|
|
|
| 126 |
}
|
| 127 |
})();
|
| 128 |
});
|