1+ <!DOCTYPE html>
2+ < html lang ="zh-CN ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6+ < title > 文件转Base64</ title >
7+ < link rel ="stylesheet " href ="../css/style.css ">
8+ </ head >
9+ < body >
10+ < div class ="tool-container ">
11+ < div class ="tool-header ">
12+ < h1 > 文件转Base64</ h1 >
13+ < p > 上传文件并将其转换为Base64编码格式</ p >
14+ </ div >
15+
16+ < div class ="tool-section ">
17+ < label class ="tool-label " for ="file-input "> 选择文件</ label >
18+ < input type ="file " id ="file-input " class ="tool-input " accept ="*/* ">
19+ </ div >
20+
21+ < div class ="tool-section " id ="file-info-section " style ="display: none; ">
22+ < h3 > 文件信息</ h3 >
23+ < div id ="file-info " class ="tool-result ">
24+ <!-- File info will be displayed here -->
25+ </ div >
26+ </ div >
27+
28+ < div class ="tool-section " id ="options-section " style ="display: none; ">
29+ < label class ="tool-label-container ">
30+ < span > 选项</ span >
31+ </ label >
32+ < div class ="tool-inline-controls ">
33+ < label class ="tool-label-inline ">
34+ < input type ="checkbox " id ="show-prefix " checked >
35+ < span > 显示数据URI前缀 (data:mime/type;base64,)</ span >
36+ </ label >
37+ </ div >
38+ </ div >
39+
40+ < div class ="tool-section " id ="output-section " style ="display: none; ">
41+ < label class ="tool-label " for ="base64-output "> Base64 输出</ label >
42+ < textarea id ="base64-output " class ="tool-textarea " placeholder ="Base64编码将显示在这里... " readonly > </ textarea >
43+ </ div >
44+
45+ < div class ="tool-controls " id ="action-buttons " style ="display: none; ">
46+ < button class ="tool-button " id ="copy-button "> 复制</ button >
47+ < button class ="tool-button " onclick ="clearAll() "> 清除</ button >
48+ </ div >
49+
50+ < div class ="tool-error " id ="error-message "> </ div >
51+ </ div >
52+
53+ < script >
54+ const fileInput = document . getElementById ( 'file-input' ) ;
55+ const fileInfoSection = document . getElementById ( 'file-info-section' ) ;
56+ const fileInfo = document . getElementById ( 'file-info' ) ;
57+ const optionsSection = document . getElementById ( 'options-section' ) ;
58+ const outputSection = document . getElementById ( 'output-section' ) ;
59+ const base64Output = document . getElementById ( 'base64-output' ) ;
60+ const actionButtons = document . getElementById ( 'action-buttons' ) ;
61+ const showPrefixCheckbox = document . getElementById ( 'show-prefix' ) ;
62+ const errorMessage = document . getElementById ( 'error-message' ) ;
63+ const copyButton = document . getElementById ( 'copy-button' ) ;
64+
65+ fileInput . addEventListener ( 'change' , handleFileSelect ) ;
66+ copyButton . addEventListener ( 'click' , copyToClipboard ) ;
67+
68+ function handleFileSelect ( event ) {
69+ const file = event . target . files [ 0 ] ;
70+ if ( ! file ) {
71+ return ;
72+ }
73+
74+ // Clear previous errors
75+ errorMessage . textContent = '' ;
76+
77+ // Display file information
78+ displayFileInfo ( file ) ;
79+
80+ // Convert file to base64
81+ convertFileToBase64 ( file ) ;
82+ }
83+
84+ function displayFileInfo ( file ) {
85+ const fileSizeKB = ( file . size / 1024 ) . toFixed ( 2 ) ;
86+ fileInfo . innerHTML = `
87+ <strong>文件名:</strong> ${ file . name } <br>
88+ <strong>文件大小:</strong> ${ fileSizeKB } KB<br>
89+ <strong>文件类型:</strong> ${ file . type || '未知' }
90+ ` ;
91+ fileInfoSection . style . display = 'block' ;
92+ optionsSection . style . display = 'block' ;
93+ }
94+
95+ function convertFileToBase64 ( file ) {
96+ const reader = new FileReader ( ) ;
97+
98+ reader . onload = function ( e ) {
99+ let base64String = e . target . result ;
100+
101+ // Update output based on prefix checkbox
102+ updateBase64Output ( base64String ) ;
103+
104+ // Show output and action buttons
105+ outputSection . style . display = 'block' ;
106+ actionButtons . style . display = 'flex' ;
107+ } ;
108+
109+ reader . onerror = function ( e ) {
110+ errorMessage . textContent = '文件读取错误: ' + e . target . error ;
111+ hideOutputSections ( ) ;
112+ } ;
113+
114+ reader . readAsDataURL ( file ) ;
115+ }
116+
117+ function updateBase64Output ( base64String ) {
118+ const showPrefix = showPrefixCheckbox . checked ;
119+
120+ if ( ! showPrefix ) {
121+ // Remove the data URI prefix to get pure base64
122+ const commaIndex = base64String . indexOf ( ',' ) ;
123+ if ( commaIndex !== - 1 ) {
124+ base64String = base64String . substring ( commaIndex + 1 ) ;
125+ }
126+ }
127+
128+ base64Output . value = base64String ;
129+ }
130+
131+ showPrefixCheckbox . addEventListener ( 'change' , function ( ) {
132+ if ( base64Output . value ) {
133+ // Re-process the current file with new prefix setting
134+ const file = fileInput . files [ 0 ] ;
135+ if ( file ) {
136+ convertFileToBase64 ( file ) ;
137+ }
138+ }
139+ } ) ;
140+
141+ function copyToClipboard ( ) {
142+ if ( ! base64Output . value ) {
143+ errorMessage . textContent = '没有内容可复制' ;
144+ return ;
145+ }
146+
147+ // Try modern clipboard API first
148+ if ( navigator . clipboard && navigator . clipboard . writeText ) {
149+ navigator . clipboard . writeText ( base64Output . value )
150+ . then ( ( ) => {
151+ showCopySuccess ( ) ;
152+ } )
153+ . catch ( err => {
154+ // If modern API fails, try fallback method
155+ fallbackCopyToClipboard ( ) ;
156+ } ) ;
157+ } else {
158+ // Use fallback method for older browsers
159+ fallbackCopyToClipboard ( ) ;
160+ }
161+ }
162+
163+ function fallbackCopyToClipboard ( ) {
164+ // Select the text
165+ base64Output . select ( ) ;
166+ base64Output . setSelectionRange ( 0 , 99999 ) ; // For mobile devices
167+
168+ try {
169+ // Try to copy using execCommand
170+ const successful = document . execCommand ( 'copy' ) ;
171+ if ( successful ) {
172+ showCopySuccess ( ) ;
173+ } else {
174+ errorMessage . textContent = '复制失败,请手动选择并复制文本' ;
175+ }
176+ } catch ( err ) {
177+ errorMessage . textContent = '复制失败,请手动选择并复制文本' ;
178+ }
179+
180+ // Deselect the text
181+ base64Output . setSelectionRange ( 0 , 0 ) ;
182+ base64Output . blur ( ) ;
183+ }
184+
185+ function showCopySuccess ( ) {
186+ // Show temporary success message
187+ const originalText = copyButton . textContent ;
188+ copyButton . textContent = '已复制!' ;
189+ copyButton . style . backgroundColor = '#28a745' ;
190+
191+ setTimeout ( ( ) => {
192+ copyButton . textContent = originalText ;
193+ copyButton . style . backgroundColor = '' ;
194+ } , 2000 ) ;
195+ }
196+
197+ function clearAll ( ) {
198+ // Reset all elements
199+ fileInput . value = '' ;
200+ base64Output . value = '' ;
201+ errorMessage . textContent = '' ;
202+
203+ // Hide sections
204+ fileInfoSection . style . display = 'none' ;
205+ optionsSection . style . display = 'none' ;
206+ outputSection . style . display = 'none' ;
207+ actionButtons . style . display = 'none' ;
208+
209+ // Reset file info
210+ fileInfo . innerHTML = '' ;
211+ }
212+
213+ function hideOutputSections ( ) {
214+ outputSection . style . display = 'none' ;
215+ actionButtons . style . display = 'none' ;
216+ }
217+ </ script >
218+ </ body >
219+ </ html >
0 commit comments