-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
150 lines (136 loc) · 6.17 KB
/
Copy pathapp.js
File metadata and controls
150 lines (136 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Dependencias
import express from "express";
import multer from "multer";
import axios from "axios";
import fs from "fs";
import FormData from "form-data";
import dotenv from "dotenv";
dotenv.config();
const app = express();
const upload = multer({ dest: "uploads/" });
const API_KEY = process.env.API_KEY;
// Página de Inicio con Formulario de Subida de Imagen y Prompt
app.get("/", (req, res) => {
res.send(`
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sube tu Imagen de Ultrasonido</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f0f8ff; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
.container { text-align: center; background-color: #ffffff; border: 2px dashed #0073e6; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); padding: 40px; width: 80%; max-width: 400px; color: #555; }
h1 { font-size: 20px; color: #0073e6; margin-bottom: 20px; }
#drop-area { border: 2px dashed #0073e6; padding: 30px; border-radius: 8px; cursor: pointer; background-color: #f9f9f9; }
#drop-area:hover { background-color: #e6f3ff; }
.instructions { font-size: 14px; color: #333; margin-top: 10px; }
</style>
</head>
<body>
<div class="container">
<h1>Sube tu Imagen de Ultrasonido</h1>
<form action="/upload" method="POST" enctype="multipart/form-data" id="upload-form">
<div id="drop-area">
<p>Arrastra tu imagen aquí o haz clic para seleccionar</p>
<input type="file" name="image" id="image" accept=".jpeg, .jpg, .png, .webp" style="display: none;" required />
</div>
<div class="instructions">Solo se aceptan imágenes JPEG, PNG o WEBP menores a 5MB.</div>
</form>
</div>
<script>
const dropArea = document.getElementById("drop-area");
const fileInput = document.getElementById("image");
const form = document.getElementById("upload-form");
dropArea.addEventListener("click", () => fileInput.click());
fileInput.addEventListener("change", () => { const file = fileInput.files[0]; if (validateFile(file)) form.submit(); });
dropArea.addEventListener("dragover", (e) => { e.preventDefault(); dropArea.style.backgroundColor = "#e6f3ff"; });
dropArea.addEventListener("dragleave", () => { dropArea.style.backgroundColor = "#f9f9f9"; });
dropArea.addEventListener("drop", (e) => { e.preventDefault(); dropArea.style.backgroundColor = "#f9f9f9"; const file = e.dataTransfer.files[0]; if (validateFile(file)) { fileInput.files = e.dataTransfer.files; form.submit(); } });
function validateFile(file) { const validTypes = ["image/jpeg", "image/png", "image/webp"]; const maxSize = 5 * 1024 * 1024; if (!validTypes.includes(file.type)) { alert("Solo se aceptan archivos JPEG, PNG o WEBP."); return false; } if (file.size > maxSize) { alert("El archivo debe ser menor a 5MB."); return false; } return true; }
</script>
</body>
</html>
`);
});
// Ruta POST para procesar la imagen y el prompt
app.post("/upload", upload.single("image"), async (req, res) => {
try {
const imagePath = req.file.path;
if (!imagePath) {
throw new Error("No se ha recibido un archivo de imagen válido.");
}
const formData = new FormData();
formData.append("image", fs.createReadStream(imagePath));
formData.append("prompt", process.env.POSITIVE_PROMPT || "Default positive prompt");
formData.append("negative_prompt", process.env.NEGATIVE_PROMPT || "Default negative prompt");
formData.append("output_format", process.env.OUTPUT_FORMAT || "webp");
const response = await axios.post(
"https://api.stability.ai/v2beta/stable-image/upscale/creative",
formData,
{
headers: {
...formData.getHeaders(),
Authorization: `Bearer ${API_KEY}`,
},
}
);
if (response.status === 200) {
const generationID = response.data.id;
res.send(`
<html>
<head>
<meta http-equiv="refresh" content="5;url=/result/${generationID}" />
</head>
<body>
<p>Imagen en proceso de generación con ID: ${generationID}</p>
<p>Serás redirigido automáticamente en unos segundos. Si no ocurre, <a href="/result/${generationID}">haz clic aquí para ver el resultado</a>.</p>
</body>
</html>
`);
} else {
console.error("Error en la generación:", response.data.errors);
throw new Error(`Error al generar la imagen: ${response.data.errors || response.data}`);
}
} catch (error) {
console.error("Error en la solicitud:", error.response ? error.response.data : error.message);
res.status(500).send(`Error: ${error.response ? JSON.stringify(error.response.data) : error.message}`);
} finally {
if (req.file && req.file.path) fs.unlinkSync(req.file.path); // Borrar el archivo subido
}
});
// Ruta GET para obtener y mostrar el resultado generado
app.get("/result/:generationID", async (req, res) => {
const { generationID } = req.params;
try {
const response = await axios.get(
`https://api.stability.ai/v2beta/stable-image/upscale/creative/result/${generationID}`,
{
responseType: "arraybuffer",
headers: {
Authorization: `Bearer ${API_KEY}`,
Accept: "image/*",
},
}
);
if (response.status === 202) {
res.send("<p>La generación aún está en proceso. Vuelve a intentarlo en unos segundos.</p>");
} else if (response.status === 200) {
const imageBuffer = Buffer.from(response.data, "binary");
res.writeHead(200, {
"Content-Type": "image/webp",
"Content-Length": imageBuffer.length,
});
res.end(imageBuffer);
} else {
throw new Error(`Error: ${response.status} - ${response.data}`);
}
} catch (error) {
res.status(500).send(`Error al obtener la imagen generada: ${error.message}`);
}
});
// Iniciar el servidor
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Servidor corriendo en http://localhost:${PORT}`);
});