@@ -115,7 +115,7 @@ <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-dark mb-2">
115115 <!-- 进度和结果 -->
116116 < div id ="progressArea " class ="hidden mb-8 ">
117117 < div class ="bg-gray-200 rounded-full h-2.5 mb-2 ">
118- < div id ="progressBar " class ="bg-primary h-2.5 rounded-full " style ="width: 0% "> </ div >
118+ < div id ="progressBar " class ="bg-primary h-2.5 rounded-full transition-all duration-300 " style ="width: 0% "> </ div >
119119 </ div >
120120 < p id ="progressText " class ="text-gray-600 text-center "> 准备中...</ p >
121121 </ div >
@@ -213,13 +213,19 @@ <h3 class="text-lg font-medium text-gray-800">文件处理完成!</h3>
213213 } ) ;
214214
215215 // 点击上传区域触发文件选择
216- fileDropArea . addEventListener ( 'click' , function ( ) {
217- fileInput . click ( ) ;
216+ fileDropArea . addEventListener ( 'click' , function ( e ) {
217+ // 只有点击区域不是按钮时才触发文件选择
218+ if ( ! e . target . closest ( 'label' ) && ! e . target . closest ( 'button' ) ) {
219+ fileInput . click ( ) ;
220+ }
218221 } ) ;
219222
220223 // 处理选中的文件
221224 function handleFile ( file ) {
225+ if ( ! file ) return ;
226+
222227 selectedFile = file ;
228+ // 确保文件名显示正确
223229 fileName . textContent = `已选择: ${ file . name } (${ formatFileSize ( file . size ) } )` ;
224230 fileName . classList . remove ( 'hidden' ) ;
225231 processBtn . disabled = false ;
@@ -293,47 +299,65 @@ <h3 class="text-lg font-medium text-gray-800">文件处理完成!</h3>
293299
294300 // 损坏数据:从文件头之后开始,每隔damageInterval字节,损坏2字节
295301 let modifiedCount = 0 ;
302+ const totalSteps = Math . ceil ( dataSize / damageInterval ) ;
303+ let currentStep = 0 ;
296304
297- for ( let i = actualHeaderLength ; i < fileSize ; i += damageInterval ) {
298- // 更新进度
299- const progress = 20 + Math . floor ( ( i / fileSize ) * 70 ) ;
300- updateProgress ( progress , `正在损坏数据... (${ modifiedCount } 处)` ) ;
305+ // 使用requestAnimationFrame优化大文件进度显示
306+ function processNextChunk ( ) {
307+ // 计算当前批次处理的位置
308+ const i = actualHeaderLength + currentStep * damageInterval ;
309+
310+ if ( i >= fileSize ) {
311+ // 处理完成
312+ updateProgress ( 100 , '处理完成!' ) ;
313+
314+ // 创建处理后的文件
315+ processedBlob = new Blob ( [ byteArray ] , { type : selectedFile . type } ) ;
316+ const nameParts = selectedFile . name . split ( '.' ) ;
317+ if ( nameParts . length > 1 ) {
318+ const ext = nameParts . pop ( ) ;
319+ processedFileName = `${ nameParts . join ( '.' ) } _damaged.${ ext } ` ;
320+ } else {
321+ processedFileName = `${ selectedFile . name } _damaged` ;
322+ }
323+
324+ // 显示结果
325+ resultInfo . textContent = `已在文件中损坏 ${ modifiedCount / 2 } 处,共 ${ modifiedCount } 字节` ;
326+ setTimeout ( ( ) => {
327+ progressArea . classList . add ( 'hidden' ) ;
328+ resultArea . classList . remove ( 'hidden' ) ;
329+ } , 500 ) ;
330+ return ;
331+ }
301332
302333 // 损坏接下来的2字节,确保不超出文件范围
303334 for ( let j = 0 ; j < 2 && i + j < fileSize ; j ++ ) {
304335 // 生成随机字节值 (0-255)
305336 byteArray [ i + j ] = Math . floor ( Math . random ( ) * 256 ) ;
306337 modifiedCount ++ ;
307338 }
339+
340+ // 更新进度
341+ currentStep ++ ;
342+ const progress = 20 + Math . floor ( ( currentStep / totalSteps ) * 70 ) ;
343+ updateProgress ( progress , `正在损坏数据... (${ Math . floor ( currentStep / totalSteps * 100 ) } %)` ) ;
344+
345+ // 继续处理下一批
346+ requestAnimationFrame ( processNextChunk ) ;
308347 }
309-
310- // 完成处理
311- updateProgress ( 100 , '处理完成!' ) ;
312348
313- // 创建处理后的文件
314- processedBlob = new Blob ( [ byteArray ] , { type : selectedFile . type } ) ;
315- const nameParts = selectedFile . name . split ( '.' ) ;
316- if ( nameParts . length > 1 ) {
317- const ext = nameParts . pop ( ) ;
318- processedFileName = `${ nameParts . join ( '.' ) } _damaged.${ ext } ` ;
319- } else {
320- processedFileName = `${ selectedFile . name } _damaged` ;
321- }
322-
323- // 显示结果
324- resultInfo . textContent = `已在文件中损坏 ${ modifiedCount / 2 } 处,共 ${ modifiedCount } 字节` ;
325- setTimeout ( ( ) => {
326- progressArea . classList . add ( 'hidden' ) ;
327- resultArea . classList . remove ( 'hidden' ) ;
328- } , 500 ) ;
349+ // 开始分块处理
350+ processNextChunk ( ) ;
329351
330352 } catch ( error ) {
353+ console . error ( '处理错误:' , error ) ;
331354 showError ( `处理文件时出错: ${ error . message } ` ) ;
332355 }
333356 } ;
334357
335358 reader . onerror = function ( ) {
336- showError ( '读取文件时出错' ) ;
359+ console . error ( '读取错误:' , reader . error ) ;
360+ showError ( '读取文件时出错: ' + reader . error . message ) ;
337361 } ;
338362
339363 // 读取文件为ArrayBuffer
@@ -356,14 +380,29 @@ <h3 class="text-lg font-medium text-gray-800">文件处理完成!</h3>
356380 // 下载处理后的文件
357381 downloadBtn . addEventListener ( 'click' , function ( ) {
358382 if ( processedBlob && processedFileName ) {
359- const url = URL . createObjectURL ( processedBlob ) ;
360- const a = document . createElement ( 'a' ) ;
361- a . href = url ;
362- a . download = processedFileName ;
363- document . body . appendChild ( a ) ;
364- a . click ( ) ;
365- document . body . removeChild ( a ) ;
366- URL . revokeObjectURL ( url ) ;
383+ try {
384+ const url = URL . createObjectURL ( processedBlob ) ;
385+ const a = document . createElement ( 'a' ) ;
386+ a . href = url ;
387+ a . download = processedFileName ;
388+ document . body . appendChild ( a ) ;
389+ // 模拟点击下载
390+ const clickEvent = new MouseEvent ( 'click' , {
391+ view : window ,
392+ bubbles : true ,
393+ cancelable : true
394+ } ) ;
395+ a . dispatchEvent ( clickEvent ) ;
396+
397+ // 清理
398+ setTimeout ( ( ) => {
399+ document . body . removeChild ( a ) ;
400+ URL . revokeObjectURL ( url ) ;
401+ } , 100 ) ;
402+ } catch ( error ) {
403+ console . error ( '下载错误:' , error ) ;
404+ showError ( '下载文件时出错: ' + error . message ) ;
405+ }
367406 }
368407 } ) ;
369408 </ script >
0 commit comments