@@ -53,6 +53,77 @@ public class FileController {
5353 private final String demoPath = demoDir + File .separator ;
5454 public static final String BASE64_DECODE_ERROR_MSG = "Base64解码失败,请检查你的 %s 是否采用 Base64 + urlEncode 双重编码了!" ;
5555
56+ @ PostMapping ("/fileUpload" )
57+ public ReturnResponse <Object > fileUpload (@ RequestParam ("file" ) MultipartFile file ) {
58+ ReturnResponse <Object > checkResult = this .fileUploadCheck (file );
59+ if (checkResult .isFailure ()) {
60+ return checkResult ;
61+ }
62+ File outFile = new File (fileDir + demoPath );
63+ if (!outFile .exists () && !outFile .mkdirs ()) {
64+ logger .error ("创建文件夹【{}】失败,请检查目录权限!" , fileDir + demoPath );
65+ }
66+ String fileName = checkResult .getContent ().toString ();
67+ logger .info ("上传文件:{}{}{}" , fileDir , demoPath , fileName );
68+ try (InputStream in = file .getInputStream (); OutputStream out = Files .newOutputStream (Paths .get (fileDir + demoPath + fileName ))) {
69+ StreamUtils .copy (in , out );
70+ return ReturnResponse .success (null );
71+ } catch (IOException e ) {
72+ logger .error ("文件上传失败" , e );
73+ return ReturnResponse .failure ();
74+ }
75+ }
76+
77+ @ GetMapping ("/deleteFile" )
78+ public ReturnResponse <Object > deleteFile (HttpServletRequest request , String fileName , String password ) {
79+ ReturnResponse <Object > checkResult = this .deleteFileCheck (request , fileName , password );
80+ if (checkResult .isFailure ()) {
81+ return checkResult ;
82+ }
83+ fileName = checkResult .getContent ().toString ();
84+ File file = new File (fileDir + demoPath + fileName );
85+ logger .info ("删除文件:{}" , file .getAbsolutePath ());
86+ if (file .exists () && !file .delete ()) {
87+ String msg = String .format ("删除文件【%s】失败,请检查目录权限!" , file .getPath ());
88+ logger .error (msg );
89+ return ReturnResponse .failure (msg );
90+ }
91+ WebUtils .removeSessionAttr (request , CAPTCHA_CODE ); //删除缓存验证码
92+ return ReturnResponse .success ();
93+ }
94+
95+ /**
96+ * 验证码方法
97+ */
98+ @ RequestMapping ("/deleteFile/captcha" )
99+ public void captcha (HttpServletRequest request , HttpServletResponse response ) throws Exception {
100+ if (!ConfigConstants .getDeleteCaptcha ()) {
101+ return ;
102+ }
103+
104+ response .setContentType ("image/jpeg" );
105+ response .setHeader ("Pragma" , "no-cache" );
106+ response .setHeader ("Cache-Control" , "no-cache" );
107+ response .setDateHeader ("Expires" , -1 );
108+ String captchaCode = WebUtils .getSessionAttr (request , CAPTCHA_CODE );
109+ long captchaGenerateTime = WebUtils .getLongSessionAttr (request , CAPTCHA_GENERATE_TIME );
110+ long timeDifference = DateUtils .calculateCurrentTimeDifference (captchaGenerateTime );
111+
112+ // 验证码为空,且生成验证码超过50秒,重新生成验证码
113+ if (timeDifference > 50 && ObjectUtils .isEmpty (captchaCode )) {
114+ captchaCode = CaptchaUtil .generateCaptchaCode ();
115+ // 更新验证码
116+ WebUtils .setSessionAttr (request , CAPTCHA_CODE , captchaCode );
117+ WebUtils .setSessionAttr (request , CAPTCHA_GENERATE_TIME , DateUtils .getCurrentSecond ());
118+ } else {
119+ captchaCode = ObjectUtils .isEmpty (captchaCode ) ? "wait" : captchaCode ;
120+ }
121+
122+ ServletOutputStream outputStream = response .getOutputStream ();
123+ ImageIO .write (CaptchaUtil .generateCaptchaPic (captchaCode ), "jpeg" , outputStream );
124+ outputStream .close ();
125+ }
126+
56127 @ GetMapping ("/listFiles" )
57128 public List <Map <String , String >> getFiles () {
58129 List <Map <String , String >> list = new ArrayList <>();
@@ -69,6 +140,70 @@ public List<Map<String, String>> getFiles() {
69140 return list ;
70141 }
71142
143+ /**
144+ * 上传文件前校验
145+ *
146+ * @param file 文件
147+ * @return 校验结果
148+ */
149+ private ReturnResponse <Object > fileUploadCheck (MultipartFile file ) {
150+ if (ConfigConstants .getFileUploadDisable ()) {
151+ return ReturnResponse .failure ("文件传接口已禁用" );
152+ }
153+ String fileName = WebUtils .getFileNameFromMultipartFile (file );
154+ if (fileName .lastIndexOf ("." ) == -1 ) {
155+ return ReturnResponse .failure ("不允许上传的类型" );
156+ }
157+ if (!KkFileUtils .isAllowedUpload (fileName )) {
158+ return ReturnResponse .failure ("不允许上传的文件类型: " + fileName );
159+ }
160+ if (KkFileUtils .isIllegalFileName (fileName )) {
161+ return ReturnResponse .failure ("不允许上传的文件名: " + fileName );
162+ }
163+ // 判断是否存在同名文件
164+ if (existsFile (fileName )) {
165+ return ReturnResponse .failure ("存在同名文件,请先删除原有文件再次上传" );
166+ }
167+ return ReturnResponse .success (fileName );
168+ }
169+
170+
171+ /**
172+ * 删除文件前校验
173+ *
174+ * @param fileName 文件名
175+ * @return 校验结果
176+ */
177+ private ReturnResponse <Object > deleteFileCheck (HttpServletRequest request , String fileName , String password ) {
178+ if (ObjectUtils .isEmpty (fileName )) {
179+ return ReturnResponse .failure ("文件名为空,删除失败!" );
180+ }
181+ try {
182+ fileName = WebUtils .decodeUrl (fileName );
183+ } catch (Exception ex ) {
184+ String errorMsg = String .format (BASE64_DECODE_ERROR_MSG , fileName );
185+ return ReturnResponse .failure (errorMsg + "删除失败!" );
186+ }
187+ assert fileName != null ;
188+ if (fileName .contains ("/" )) {
189+ fileName = fileName .substring (fileName .lastIndexOf ("/" ) + 1 );
190+ }
191+ if (KkFileUtils .isIllegalFileName (fileName )) {
192+ return ReturnResponse .failure ("非法文件名,删除失败!" );
193+ }
194+ if (ObjectUtils .isEmpty (password )) {
195+ return ReturnResponse .failure ("密码 or 验证码为空,删除失败!" );
196+ }
197+
198+ String expectedPassword = ConfigConstants .getDeleteCaptcha () ? WebUtils .getSessionAttr (request , CAPTCHA_CODE ) : ConfigConstants .getPassword ();
199+
200+ if (!password .equalsIgnoreCase (expectedPassword )) {
201+ logger .error ("删除文件【{}】失败,密码错误!" , fileName );
202+ return ReturnResponse .failure ("删除文件失败,密码错误!" );
203+ }
204+ return ReturnResponse .success (fileName );
205+ }
206+
72207 @ GetMapping ("/directory" )
73208 public Object directory (String urls ) {
74209 String fileUrl ;
@@ -84,4 +219,9 @@ public Object directory(String urls) {
84219 }
85220 return RarUtils .getTree (fileUrl );
86221 }
222+
223+ private boolean existsFile (String fileName ) {
224+ File file = new File (fileDir + demoPath + fileName );
225+ return file .exists ();
226+ }
87227}
0 commit comments