comparison mrjunejune/src/tools/file_converter/index.html @ 92:655ea0b661fd

[Seobeo] Added few endpoints for handling files. [Dowa] Added few functions for random number and generating uuids
author June Park <parkjune1995@gmail.com>
date Fri, 02 Jan 2026 17:47:10 -0800
parents
children be91a73d801a
comparison
equal deleted inserted replaced
91:19cccf6e866a 92:655ea0b661fd
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>File Format Converter</title>
7 {{/parts/base_head.html}}
8 <style>
9 .container {
10 max-width: 800px;
11 margin: 2rem auto;
12 padding: 2rem;
13 }
14
15 .converter-section {
16 border-radius: 8px;
17 border: 2px solid var(--lightgray);
18 padding: 2rem;
19 margin-bottom: 2rem;
20 }
21
22 .converter-section h2 {
23 margin-top: 0;
24 color: var(--black);
25 }
26
27 .file-input-wrapper {
28 margin: 1rem 0;
29 }
30
31 .file-input-wrapper label {
32 display: block;
33 margin-bottom: 0.5rem;
34 font-weight: 600;
35 }
36
37 input[type="file"] {
38 width: 50%;
39 padding: 0.5rem;
40 border: 2px dashed #ccc;
41 border-radius: 4px;
42 background: white;
43 }
44
45 button {
46 background: var(--purple);
47 font-family: "More Thin", sans-serif;
48 color: var(--gray-gradient);
49 border: none;
50 padding: 0.75rem 1.5rem;
51 border-radius: 4px;
52 cursor: pointer;
53 font-size: 1rem;
54 margin-top: 1rem;
55 }
56
57 button:hover {
58 background: var(--orange);
59 }
60
61 button:disabled {
62 background: var(--gray);
63 cursor: not-allowed;
64 }
65
66 .result {
67 margin-top: 1rem;
68 padding: 1rem;
69 background: white;
70 border-radius: 4px;
71 display: none;
72 }
73
74 .result.show {
75 display: block;
76 }
77
78 .result.success {
79 border-left: 4px solid var(--blue);
80 }
81
82 .result.error {
83 border-left: 4px solid var(--red);
84 }
85
86 .download-link {
87 display: inline-block;
88 margin-top: 0.5rem;
89 color: var(--awesome);
90 text-decoration: none;
91 }
92
93 .download-link:hover {
94 text-decoration: underline;
95 }
96
97 .loading {
98 display: none;
99 margin-top: 1rem;
100 }
101
102 .loading.show {
103 display: block;
104 }
105 </style>
106 </head>
107 <body>
108 {{/parts/header.html}}
109
110 <div class="container">
111 <h1>File Format Converter</h1>
112 <p>Convert your images and videos to different formats using FFmpeg</p>
113
114 <div class="converter-section">
115 <h2>Image to WebP Converter</h2>
116 <p>Upload an image file (PNG, JPG, GIF, etc.) to convert it to WebP format</p>
117
118 <div class="file-input-wrapper">
119 <label for="imageInput">Choose an image file:</label>
120 <input type="file" id="imageInput" accept="image/*">
121 </div>
122
123 <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
124
125 <div class="loading" id="imageLoading">Converting... Please wait.</div>
126
127 <div class="result" id="imageResult">
128 <p id="imageMessage"></p>
129 <a id="imageDownload" class="download-link" style="display: none;">Download WebP Image</a>
130 </div>
131 </div>
132
133 <div class="converter-section">
134 <h2>Video to MP4 Converter</h2>
135 <p>Upload a video file (AVI, MOV, MKV, etc.) to convert it to MP4 format</p>
136
137 <div class="file-input-wrapper">
138 <label for="videoInput">Choose a video file:</label>
139 <input type="file" id="videoInput" accept="video/*">
140 </div>
141
142 <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
143
144 <div class="loading" id="videoLoading">Converting... Please wait.</div>
145
146 <div class="result" id="videoResult">
147 <p id="videoMessage"></p>
148 <a id="videoDownload" class="download-link" style="display: none;">Download MP4 Video</a>
149 </div>
150 </div>
151 </div>
152
153 <script>
154 async function convertImageToWebP() {
155 const input = document.getElementById('imageInput');
156 const btn = document.getElementById('convertImageBtn');
157 const loading = document.getElementById('imageLoading');
158 const result = document.getElementById('imageResult');
159 const message = document.getElementById('imageMessage');
160 const download = document.getElementById('imageDownload');
161
162 if (!input.files || !input.files[0]) {
163 alert('Please select an image file first');
164 return;
165 }
166
167 const file = input.files[0];
168
169 // Show loading state
170 btn.disabled = true;
171 loading.classList.add('show');
172 result.classList.remove('show', 'success', 'error');
173 download.style.display = 'none';
174
175 try {
176 const response = await fetch('/api/convert/image-to-webp', {
177 method: 'POST',
178 body: file,
179 headers: {
180 'Content-Type': file.type
181 }
182 });
183
184 loading.classList.remove('show');
185 result.classList.add('show');
186
187 if (response.ok) {
188 const data = await response.json();
189
190 download.href = data.download_url;
191 download.download = file.name.replace(/\.[^/.]+$/, '') + '.webp';
192 download.style.display = 'inline-block';
193
194 message.textContent = 'Conversion successful! Link expires in ' + data.expires + '.';
195 result.classList.add('success');
196 } else {
197 const text = await response.text();
198 message.textContent = 'Conversion failed: ' + text;
199 result.classList.add('error');
200 }
201 } catch (error) {
202 loading.classList.remove('show');
203 result.classList.add('show', 'error');
204 message.textContent = 'Error: ' + error.message;
205 } finally {
206 btn.disabled = false;
207 }
208 }
209
210 async function convertVideoToMP4() {
211 const input = document.getElementById('videoInput');
212 const btn = document.getElementById('convertVideoBtn');
213 const loading = document.getElementById('videoLoading');
214 const result = document.getElementById('videoResult');
215 const message = document.getElementById('videoMessage');
216 const download = document.getElementById('videoDownload');
217
218 if (!input.files || !input.files[0]) {
219 alert('Please select a video file first');
220 return;
221 }
222
223 const file = input.files[0];
224
225 // Show loading state
226 btn.disabled = true;
227 loading.classList.add('show');
228 result.classList.remove('show', 'success', 'error');
229 download.style.display = 'none';
230
231 try {
232 const response = await fetch('/api/convert/video-to-mp4', {
233 method: 'POST',
234 body: file,
235 headers: {
236 'Content-Type': file.type
237 }
238 });
239
240 loading.classList.remove('show');
241 result.classList.add('show');
242
243 if (response.ok) {
244 const data = await response.json();
245
246 download.href = data.download_url;
247 download.download = file.name.replace(/\.[^/.]+$/, '') + '.mp4';
248 download.style.display = 'inline-block';
249
250 message.textContent = 'Conversion successful! Link expires in ' + data.expires + '.';
251 result.classList.add('success');
252 } else {
253 const text = await response.text();
254 message.textContent = 'Conversion failed: ' + text;
255 result.classList.add('error');
256 }
257 } catch (error) {
258 loading.classList.remove('show');
259 result.classList.add('show', 'error');
260 message.textContent = 'Error: ' + error.message;
261 } finally {
262 btn.disabled = false;
263 }
264 }
265 </script>
266 </body>
267 </html>