diff --git a/server/src/main/java/cn/keking/utils/DateUtils.java b/server/src/main/java/cn/keking/utils/DateUtils.java index 84436a47f..7d255e05e 100644 --- a/server/src/main/java/cn/keking/utils/DateUtils.java +++ b/server/src/main/java/cn/keking/utils/DateUtils.java @@ -1,6 +1,9 @@ package cn.keking.utils; import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; /** * @author kl (http://kailing.pub) @@ -23,4 +26,17 @@ public static long getCurrentSecond() { public static long calculateCurrentTimeDifference(long datetime) { return getCurrentSecond() - datetime; } + + /** + * 将时间戳格式化为可读字符串 + * @param timestamp 时间戳(毫秒) + * @return 格式化后的时间字符串 + */ + public static String formatTime(long timestamp) { + LocalDateTime dateTime = LocalDateTime.ofInstant( + Instant.ofEpochMilli(timestamp), + ZoneId.systemDefault() + ); + return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } } diff --git a/server/src/main/java/cn/keking/web/controller/FileController.java b/server/src/main/java/cn/keking/web/controller/FileController.java index 0ea6a9140..b99e2bb4b 100644 --- a/server/src/main/java/cn/keking/web/controller/FileController.java +++ b/server/src/main/java/cn/keking/web/controller/FileController.java @@ -13,6 +13,7 @@ import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -26,6 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -38,6 +40,30 @@ import static cn.keking.utils.CaptchaUtil.CAPTCHA_CODE; import static cn.keking.utils.CaptchaUtil.CAPTCHA_GENERATE_TIME; +/** + * 批量删除文件请求模型 + */ +class BatchDeleteRequest { + private List fileNames; + private String password; + + public List getFileNames() { + return fileNames; + } + + public void setFileNames(List fileNames) { + this.fileNames = fileNames; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} + /** * @author yudian-it * 2017/12/1 @@ -55,23 +81,50 @@ public class FileController { @PostMapping("/fileUpload") public ReturnResponse fileUpload(@RequestParam("file") MultipartFile file) { - ReturnResponse checkResult = this.fileUploadCheck(file); - if (checkResult.isFailure()) { - return checkResult; + // 将单个文件转为数组,调用批量上传方法 + MultipartFile[] files = new MultipartFile[]{file}; + return batchFileUpload(files); + } + + @PostMapping("/batchFileUpload") + public ReturnResponse batchFileUpload(@RequestParam("files") MultipartFile[] files) { + if (files == null || files.length == 0) { + return ReturnResponse.failure("没有选择文件"); } - File outFile = new File(fileDir + demoPath); - if (!outFile.exists() && !outFile.mkdirs()) { - logger.error("创建文件夹【{}】失败,请检查目录权限!", fileDir + demoPath); - } - String fileName = checkResult.getContent().toString(); - logger.info("上传文件:{}{}{}", fileDir, demoPath, fileName); - try (InputStream in = file.getInputStream(); OutputStream out = Files.newOutputStream(Paths.get(fileDir + demoPath + fileName))) { - StreamUtils.copy(in, out); - return ReturnResponse.success(null); - } catch (IOException e) { - logger.error("文件上传失败", e); - return ReturnResponse.failure(); + + List successFiles = new ArrayList<>(); + List failureFiles = new ArrayList<>(); + + for (MultipartFile file : files) { + ReturnResponse checkResult = this.fileUploadCheck(file); + if (checkResult.isFailure()) { + failureFiles.add(file.getOriginalFilename() + "(" + checkResult.getMsg() + ")"); + continue; + } + + File outFile = new File(fileDir + demoPath); + if (!outFile.exists() && !outFile.mkdirs()) { + logger.error("创建文件夹【{}】失败,请检查目录权限!", fileDir + demoPath); + } + + String fileName = checkResult.getContent().toString(); + logger.info("上传文件:{}{}{}", fileDir, demoPath, fileName); + + try (InputStream in = file.getInputStream(); + OutputStream out = Files.newOutputStream(Paths.get(fileDir + demoPath + fileName))) { + StreamUtils.copy(in, out); + successFiles.add(fileName); + } catch (IOException e) { + logger.error("文件上传失败: " + fileName, e); + failureFiles.add(fileName); + } } + + Map result = new HashMap<>(); + result.put("success", successFiles); + result.put("failure", failureFiles); + + return ReturnResponse.success(result); } @GetMapping("/deleteFile") @@ -132,9 +185,10 @@ public List> getFiles() { File[] files = Objects.requireNonNull(file.listFiles()); Arrays.sort(files, (f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified())); Arrays.stream(files).forEach(file1 -> { - Map fileName = new HashMap<>(); - fileName.put("fileName", demoDir + "/" + file1.getName()); - list.add(fileName); + Map fileInfo = new HashMap<>(); + fileInfo.put("fileName", demoDir + "/" + file1.getName()); + fileInfo.put("uploadTime", DateUtils.formatTime(file1.lastModified())); + list.add(fileInfo); }); } return list; @@ -220,8 +274,191 @@ public Object directory(String urls) { return RarUtils.getTree(fileUrl); } + /** + * 批量删除文件名检查,不进行密码验证 + * + * @param fileName 文件名 + * @return 校验结果 + */ + private ReturnResponse batchDeleteFileCheck(String fileName) { + if (ObjectUtils.isEmpty(fileName)) { + return ReturnResponse.failure("文件名为空,删除失败!"); + } + + String decodedFileName = null; + try { + // 先进行 URL 解码再进行 Base64 解码 + String urlDecoded = java.net.URLDecoder.decode(fileName, "UTF-8"); + decodedFileName = WebUtils.decodeUrl(urlDecoded); + + if (decodedFileName == null) { + logger.error("文件名解码后为空,原始文件名: {}", fileName); + return ReturnResponse.failure("文件名解码失败,删除失败!"); + } + } catch (Exception ex) { + logger.error("文件名解码异常: " + fileName, ex); + return ReturnResponse.failure("文件名解码异常,删除失败!"); + } + + // 处理路径中的分隔符 + if (decodedFileName.contains("/")) { + decodedFileName = decodedFileName.substring(decodedFileName.lastIndexOf("/") + 1); + } + + // 检查文件名合法性 + if (KkFileUtils.isIllegalFileName(decodedFileName)) { + return ReturnResponse.failure("非法文件名,删除失败!"); + } + + return ReturnResponse.success(decodedFileName); + } + + @PostMapping("/batchDeleteFiles") + public ReturnResponse batchDeleteFiles(HttpServletRequest request, @RequestBody BatchDeleteRequest deleteRequest) { + if (deleteRequest == null || deleteRequest.getFileNames() == null || deleteRequest.getFileNames().isEmpty()) { + return ReturnResponse.failure("未选择任何文件"); + } + + String password = deleteRequest.getPassword(); + if (ObjectUtils.isEmpty(password)) { + return ReturnResponse.failure("密码 or 验证码为空,删除失败!"); + } + + String expectedPassword = ConfigConstants.getDeleteCaptcha() ? WebUtils.getSessionAttr(request, CAPTCHA_CODE) : ConfigConstants.getPassword(); + if (!password.equalsIgnoreCase(expectedPassword)) { + logger.error("批量删除文件失败,密码错误!"); + return ReturnResponse.failure("删除文件失败,密码错误!"); + } + + int successCount = 0; + int failureCount = 0; + + for (String encodedFileName : deleteRequest.getFileNames()) { + try { + // 处理前端传入的编码文件名,只做文件名检查,不重复验证密码 + ReturnResponse checkResult = this.batchDeleteFileCheck(encodedFileName); + if (checkResult.isFailure()) { + failureCount++; + continue; + } + + String fileName = checkResult.getContent().toString(); + File file = new File(fileDir + demoPath + fileName); + logger.info("批量删除文件:{}", file.getAbsolutePath()); + if (file.exists() && file.delete()) { + successCount++; + } else { + failureCount++; + logger.error("删除文件【{}】失败,请检查目录权限!", file.getPath()); + } + } catch (Exception e) { + failureCount++; + logger.error("删除文件失败: " + encodedFileName, e); + } + } + + // 如果使用验证码,删除缓存验证码 + if (ConfigConstants.getDeleteCaptcha()) { + WebUtils.removeSessionAttr(request, CAPTCHA_CODE); + } + + Map result = new HashMap<>(); + result.put("success", successCount); + result.put("failure", failureCount); + + return ReturnResponse.success(result); + } + private boolean existsFile(String fileName) { File file = new File(fileDir + demoPath + fileName); return file.exists(); } + + /** + * 处理文件下载请求 + * + * @param urlPath 经过Base64编码的文件URL + * @param response HttpServletResponse对象 + */ + @GetMapping("/download") + public void downloadFile(String urlPath, HttpServletResponse response) { + String decodedUrl; + try { + decodedUrl = WebUtils.decodeUrl(urlPath); + } catch (Exception ex) { + logger.error("文件下载失败,urlPath:{},错误信息:{}", urlPath, ex.getMessage()); + return; + } + + if (decodedUrl == null) { + return; + } + + // 先检查是否是demo目录的文件 + String fileName = decodedUrl; + boolean isDemoFile = false; + + // 处理demo目录下的文件 + if (fileName.startsWith(demoDir)) { + isDemoFile = true; + if (fileName.startsWith(demoDir + "/")) { + fileName = fileName.substring((demoDir + "/").length()); + } else if (fileName.startsWith(demoDir + "\\")) { + fileName = fileName.substring((demoDir + "\\").length()); + } else { + fileName = fileName.substring(demoDir.length()); + } + } + + // 从文件名中提取实际的文件名(不含路径) + String displayFileName = fileName; + if (displayFileName.contains("/")) { + displayFileName = displayFileName.substring(displayFileName.lastIndexOf("/") + 1); + } + if (displayFileName.contains("\\")) { + displayFileName = displayFileName.substring(displayFileName.lastIndexOf("\\") + 1); + } + + // 确定文件的实际路径 + String localFilePath; + if (isDemoFile) { + localFilePath = fileDir + demoPath + fileName; + } else { + localFilePath = fileDir + fileName; + } + + File file = new File(localFilePath); + if (!file.exists()) { + try { + response.setContentType("text/html;charset=utf-8"); + response.getWriter().write("404,您请求的文件不存在!"); + logger.error("请求的文件不存在,路径:{}", localFilePath); + return; + } catch (IOException e) { + logger.error("写入响应数据失败", e); + return; + } + } + + // 设置文件下载响应头 + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + + new String(displayFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + + // 将文件写入响应输出流 + try (InputStream inputStream = Files.newInputStream(file.toPath()); + OutputStream outputStream = response.getOutputStream()) { + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.flush(); + logger.info("文件下载成功:{}", localFilePath); + + } catch (IOException e) { + logger.error("文件下载失败,文件路径:{},错误信息:{}", localFilePath, e.getMessage()); + } + } } diff --git a/server/src/main/java/cn/keking/web/filter/AttributeSetFilter.java b/server/src/main/java/cn/keking/web/filter/AttributeSetFilter.java index 5f2088771..ff2ec23e4 100644 --- a/server/src/main/java/cn/keking/web/filter/AttributeSetFilter.java +++ b/server/src/main/java/cn/keking/web/filter/AttributeSetFilter.java @@ -40,6 +40,7 @@ private void setFileAttribute(ServletRequest request){ request.setAttribute("pdfDisableEditing", ConfigConstants.getPdfDisableEditing()); request.setAttribute("switchDisabled", ConfigConstants.getOfficePreviewSwitchDisabled()); request.setAttribute("fileUploadDisable", ConfigConstants.getFileUploadDisable()); + request.setAttribute("enableDelete", true); request.setAttribute("beian", ConfigConstants.getBeian()); request.setAttribute("size", ConfigConstants.maxSize()); request.setAttribute("deleteCaptcha", ConfigConstants.getDeleteCaptcha()); diff --git a/server/src/main/resources/web/main/index.ftl b/server/src/main/resources/web/main/index.ftl index c4ebb5f7d..011b66f8b 100644 --- a/server/src/main/resources/web/main/index.ftl +++ b/server/src/main/resources/web/main/index.ftl @@ -10,6 +10,7 @@ + @@ -145,10 +146,13 @@
<#if fileUploadDisable == false>
- +
+
+ +
@@ -189,22 +193,80 @@ $("#deleteCaptchaImg").attr("src","${baseUrl}deleteFile/captcha?timestamp=" + new Date().getTime()); }); $("#deleteCaptchaConfirmBtn").click(function() { - var fileName = $("#deleteCaptchaFileName").val(); - var deleteCaptchaText = $("#deleteCaptchaText").val(); - $.get('${baseUrl}deleteFile?fileName=' + fileName +'&password=' + deleteCaptchaText, function(data){ - if ("删除文件失败,密码错误!" === data.msg) { - alert(data.msg); - } else { - $('#table').bootstrapTable("refresh", {}); - $("#deleteCaptchaText").val(""); - $("#deleteCaptchaModal").modal("hide"); + var captcha = $("#deleteCaptchaText").val(); + var isBatch = $(this).data("isBatch"); + + if (!captcha) { + alert("请输入验证码"); + return; + } + + if (isBatch) { + // 批量删除处理 + var fileNames = $("#deleteCaptchaModal").data("fileNames"); + if (!fileNames || fileNames.length === 0) { + alert("未找到要删除的文件"); + return; } - }); + + $.ajax({ + url: '${baseUrl}batchDeleteFiles', + method: 'POST', + contentType: 'application/json', + data: JSON.stringify({ + fileNames: fileNames, + password: captcha + }), + success: function(data) { + $("#deleteCaptchaModal").modal("hide"); + if (data.code !== 0) { + alert(data.msg); + } else { + var result = data.content; + var message = "成功删除 " + result.success + " 个文件"; + if (result.failure > 0) { + message += "," + result.failure + " 个文件删除失败"; + } + alert(message); + $('#table').bootstrapTable("refresh", {}); + } + }, + error: function() { + $("#deleteCaptchaModal").modal("hide"); + alert("删除失败,请联系管理员"); + } + }); + } else { + // 单个文件删除 + var fileName = $("#deleteCaptchaModal").data("fileName"); + if (!fileName) { + alert("未找到要删除的文件"); + return; + } + + $.ajax({ + url: '${baseUrl}deleteFile?fileName=' + fileName + '&password=' + captcha, + success: function(data) { + $("#deleteCaptchaModal").modal("hide"); + if (data.code !== 0) { + alert(data.msg); + } else { + alert("删除成功"); + $('#table').bootstrapTable("refresh", {}); + } + }, + error: function() { + $("#deleteCaptchaModal").modal("hide"); + alert("删除失败,请联系管理员"); + } + }); + } }); function deleteFile(fileName) { $("#deleteCaptchaImg").click(); $("#deleteCaptchaFileName").val(fileName); $("#deleteCaptchaText").val(""); + $("#deleteCaptchaConfirmBtn").data("isBatch", false); $("#deleteCaptchaModal").modal("show"); } <#else> @@ -263,24 +325,137 @@ pagination: ${homePagination}, //是否分页 pageList: [5, 10, 20, 30, 50, 100, 200, 500], search: ${homeSearch}, //显示查询框 + sortName: 'uploadTime', // 默认按上传时间排序 + sortOrder: 'desc', // 默认降序排序 + sortStable: true, // 启用稳定排序 + checkboxHeader: true, // 显示全选复选框 + clickToSelect: true, // 点击行时选中复选框 columns: [{ + checkbox: true // 添加复选框列 + }, { field: 'fileName', - title: '文件名' + title: '文件名', + sortable: true + }, { + field: 'uploadTime', + title: '上传时间', + sortable: true }, { - field: 'action', + field: 'operation', title: '操作', - align: 'center', - width: 160 + formatter: function(value, row) { + // 预览按钮 + var openBtn = [ + '' + ]; + + // 下载按钮 + var downloadBtn = [ + '' + ]; + + // 删除按钮 + var deleteBtn = + <#if enableDelete> + [ + '' + ] + <#else> + [ + '' + ] + ; + // 拼接所有按钮 + return openBtn.join("") + downloadBtn.join("") + deleteBtn.join(""); + }, + events: { + 'click .open': function (e, value, row, index) { + var filePath = ""; + if (row.fileName) { + // 从fileName解析文件路径,假设fileName包含完整路径 + filePath = row.fileName; + + // 如果存在fileDir属性则使用它(向后兼容) + if (row.fileDir) { + filePath = row.fileDir.replace(/\\/g,"").toString() + + (row.fileName.indexOf("/") > -1 ? row.fileName.substring(row.fileName.lastIndexOf("/")+1) : row.fileName); + } + } else { + // 兜底逻辑 + filePath = row.name || ""; + } + + window.open('${baseUrl}onlinePreview?url=' + encodeURIComponent(Base64.encode('${baseUrl}' + filePath))); + }, + 'click .download': function (e, value, row, index) { + var filePath = ""; + if (row.fileName) { + // 从fileName解析文件路径,假设fileName包含完整路径 + filePath = row.fileName; + + // 如果存在fileDir属性则使用它(向后兼容) + if (row.fileDir) { + filePath = row.fileDir + (row.fileName.indexOf("/") > -1 ? row.fileName.substring(row.fileName.lastIndexOf("/")+1) : row.fileName); + } + } else { + // 兜底逻辑 + filePath = row.name || ""; + } + + // 使用新的download接口 + window.open('${baseUrl}download?urlPath=' + encodeURIComponent(Base64.encode(filePath))); + }, + 'click .delete': function (e, value, row, index) { + <#if enableDelete> + var filePath = row.fileName || (row.name || ""); + if (row.fileDir) { + filePath = row.fileDir + (row.fileName ? row.fileName : row.name); + } + + <#if deleteCaptcha> + $("#deleteCaptchaImg").click(); + // 仅使用Base64编码,不再二次URL编码 + var encodedFileName = Base64.encode('${baseUrl}' + filePath); + $("#deleteCaptchaModal").data("fileName", encodedFileName); + $("#deleteCaptchaConfirmBtn").data("isBatch", false); + $("#deleteCaptchaText").val(""); + $("#deleteCaptchaModal").modal("show"); + <#else> + var password = prompt("请输入默认密码:123456"); + if (!password) { + return; + } + // 仅使用Base64编码,不再二次URL编码 + var encodedFileName = Base64.encode('${baseUrl}' + filePath); + $.get('${baseUrl}deleteFile?fileName=' + encodedFileName +'&password=' + password, function(data){ + if ("删除文件失败,密码错误!" === data.msg) { + alert(data.msg); + } else { + $('#table').bootstrapTable("refresh", {}); + } + }); + + + } + } }] }).on('pre-body.bs.table', function (e, data) { - // 每个data添加一列用来操作 - $(data).each(function (index, item) { - item.action = "预览" + - "删除"; - }); + // 移除冗余代码,因为已经在formatter中实现了这个功能 return data; }).on('post-body.bs.table', function (e, data) { return data; + }).on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function () { + // 当选择项变化时,更新批量删除按钮状态 + var selections = $('#table').bootstrapTable('getSelections'); + $('#batchDeleteBtn').prop('disabled', selections.length === 0); }); $('#previewByUrl').on('click', function () { @@ -298,11 +473,85 @@ window.open('${baseUrl}onlinePreview?url=' + encodeURIComponent(b64Encoded)); }); + $("#batchDeleteBtn").click(function() { + var selections = $('#table').bootstrapTable('getSelections'); + if (selections.length === 0) { + return; + } + + if (window.confirm('确定要删除选中的 ' + selections.length + ' 个文件吗?')) { + <#if deleteCaptcha> + $("#deleteCaptchaImg").click(); + // 存储选中的文件名列表,仅使用Base64编码,不再二次URL编码 + var encodedFileNames = selections.map(function(item) { + var filePath = item.fileName || (item.name || ""); + if (item.fileDir) { + filePath = item.fileDir + (item.fileName ? item.fileName : (item.name || "")); + } + return Base64.encode('${baseUrl}' + filePath); + }); + $("#deleteCaptchaModal").data("fileNames", encodedFileNames); + $("#deleteCaptchaText").val(""); + $("#deleteCaptchaConfirmBtn").data("isBatch", true); + $("#deleteCaptchaModal").modal("show"); + <#else> + var password = prompt("请输入默认密码:123456"); + if (!password) { + return; + } + + // 确保文件名仅使用Base64编码,不再二次URL编码 + var encodedFileNames = selections.map(function(item) { + var filePath = item.fileName || (item.name || ""); + if (item.fileDir) { + filePath = item.fileDir + (item.fileName ? item.fileName : (item.name || "")); + } + return Base64.encode('${baseUrl}' + filePath); + }); + + $.ajax({ + url: '${baseUrl}batchDeleteFiles', + method: 'POST', + contentType: 'application/json', + data: JSON.stringify({ + fileNames: encodedFileNames, + password: password + }), + success: function(data) { + if (data.code !== 0) { + alert(data.msg); + } else { + var result = data.content; + var message = "成功删除 " + result.success + " 个文件"; + if (result.failure > 0) { + message += "," + result.failure + " 个文件删除失败"; + } + alert(message); + $('#table').bootstrapTable("refresh", {}); + } + }, + error: function() { + alert("删除失败,请联系管理员"); + } + }); + + } + }); + $("#fileUploadBtn").click(function () { - var filepath = $("#file").val(); - if(!checkFileSize(filepath)) { + if ($("#file")[0].files.length === 0) { + alert("请选择要上传的文件"); return false; } + + // 检查每个文件的大小 + var files = $("#file")[0].files; + for (var i = 0; i < files.length; i++) { + if (!checkFileSizeByFile(files[i])) { + return false; + } + } + showLoadingDiv(); $("#fileUpload").ajaxSubmit({ success: function (data) { @@ -310,48 +559,45 @@ if (1 === data.code) { alert(data.msg); } else { + var result = data.content; + if (result.success && result.success.length > 0) { + var successMsg = "成功上传 " + result.success.length + " 个文件"; + if (result.failure && result.failure.length > 0) { + successMsg += "," + result.failure.length + " 个文件上传失败:\n" + result.failure.join("\n"); + } + alert(successMsg); + } else if (result.failure && result.failure.length > 0) { + alert("所有文件上传失败:\n" + result.failure.join("\n")); + } $('#table').bootstrapTable('refresh', {}); } - $("#fileName").text(""); + $("#file").val(""); $(".loading_container").hide(); }, error: function () { alert('上传失败,请联系管理员'); $(".loading_container").hide(); }, - url: 'fileUpload', /*设置post提交到的页面*/ + url: 'batchFileUpload', /*设置post提交到的页面*/ type: "post", /*设置表单以post方法提交*/ dataType: "json" /*设置返回值类型为文本*/ }); }); }); - function checkFileSize(filepath) { + + function checkFileSizeByFile(file) { var daxiao= "${size}"; daxiao= daxiao.replace("MB",""); - // console.log(daxiao) var maxsize = daxiao * 1024 * 1024; - var errMsg = "上传的文件不能超过${size}喔!!!"; - var tipMsg = "您的浏览器暂不支持上传,确保上传文件不要超过${size},建议使用IE、FireFox、Chrome浏览器"; + var errMsg = "上传的文件 [" + file.name + "] 不能超过${size}喔!!!"; + try { - var filesize = 0; - var ua = window.navigator.userAgent; - if (ua.indexOf("MSIE") >= 1) { - //IE - var img = new Image(); - img.src = filepath; - filesize = img.fileSize; - } else { - filesize = $("#file")[0].files[0].size; //byte - } - if (filesize > 0 && filesize > maxsize) { + if (file.size > 0 && file.size > maxsize) { alert(errMsg); return false; - } else if (filesize === -1) { - alert(tipMsg); - return false; } } catch (e) { - alert("上传失败,请重试"); + alert("检查文件大小失败,请重试"); return false; } return true;