SpringBoot文件上傳控制及Java 獲取和判斷文件頭信息
之前在使用SpringBoot進行文件上傳時,遇到了很多問題。于是在翻閱了很多的博文之后,總算將上傳功能進行了相應(yīng)的完善,便在這里記錄下來,供自己以后查閱。
首先,是建立一個標(biāo)準(zhǔn)的SpringBoot 的工程,這里使用的IDE是Intellij Idea,為了方便配置,將默認(rèn)的配置文件替換為了application.yml。
1.在index.html中進行文件上傳功能,這里使用的文件上傳方式是ajax,當(dāng)然也可以按照自己的具體要求使用傳統(tǒng)的表單文件上傳。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上傳測試</title> <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script> </head> <body> <input id="file" type="file" name="file"/> <br/> <button id="upload" onclick="doUpload()">上傳</button> <progress id="progressBar" value="0" max="100"></progress> <script> function doUpload() { var fileObj = document.getElementById("file").files[0]; // js 獲取文件對象 var FileController = "/upload"; // 接收上傳文件的后臺地址 // FormData 對象 var form = new FormData(); form.append("file",fileObj); // XMLHttpRequest 對象 var xhr = new XMLHttpRequest(); //為請求添加返回處理函數(shù) xhr.onreadystatechange=function () { if(this.readyState == 4 && this.status == 200){ var b = this.responseText; if(b == "success"){ alert("上傳成功!"); }else{ alert("上傳失??!"); } } }; xhr.open("post", FileController, true); //使用進度條記錄上傳進度 xhr.upload.addEventListener("progress", progressFunction, false); xhr.send(form); } function progressFunction(evt) { var progressBar = document.getElementById("progressBar"); var percentageDiv = document.getElementById("percentage"); if (evt.lengthComputable) { progressBar.max = evt.total; progressBar.value = evt.loaded; percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%"; } } </script> </body> </html>
2.在MainController添加文件上傳的API,并返回上傳結(jié)果
@PostMapping("/upload") @ResponseBody public String upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) { String path = "E://upload//"; String fileName = file.getOriginalFilename(); System.out.println(fileName); File targetFile = new File(path); if (!targetFile.exists()) { targetFile.mkdirs(); } File saveFile=new File(path+fileName); // 保存 try { file.transferTo(saveFile); return "success"; } catch (Exception e) { e.printStackTrace(); return "fail"; } }
這時,我們進行測試,就可以發(fā)現(xiàn),文件上傳已經(jīng)完成了。
很多時候,我們在進行文件上傳時,特別是向普通用戶開放文件上傳功能時,需要對上傳文件的格式進行控制,以防止黑客將病毒腳本上傳。單純的將文件名的類型進行截取的方式非常容易遭到破解,上傳者只需要將病毒改換文件名便可以完成上傳。
這時候我們可以讀取文件的十六進制的文件頭,來判斷文件真正的格式。
因為我們發(fā)現(xiàn),在我們讀取文件的二進制數(shù)據(jù)并將其轉(zhuǎn)換為十六進制時,同類型文件的文件頭數(shù)據(jù)是相同的,即使改變了其后綴,這個數(shù)據(jù)也不會改變,例如,png文件的文件頭為“89504E47”。
首先,我們將文件的數(shù)據(jù)進行讀取
public class FileUtil { public static String getFileHeader( MultipartFile file) { InputStream is = null; String value = null; try { is = file.getInputStream(); byte[] b = new byte[4]; is.read(b, 0, b.length); value = bytesToHexString(b); } catch (Exception e) { } finally { if (null != is) { try { is.close(); } catch (IOException e) { } } } return value; } private static String bytesToHexString(byte[] src) { StringBuilder builder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } String hv; for (int i = 0; i < src.length; i++) { hv = Integer.toHexString(src[i] & 0xFF).toUpperCase(); if (hv.length() < 2) { builder.append(0); } builder.append(hv); } System.out.println(builder.toString()); return builder.toString(); } }
然后在文件上傳的api中進行調(diào)用
FileUtil.getFileHeader(file)
這時候,我們只需要進行簡單的字符串比對,判斷調(diào)用的返回值是否為“89504E47”,就可以知道上傳的是否為png文件。
下面看下 Java 獲取和判斷文件頭信息
import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; /** * 獲取和判斷文件頭信息 * * @author Sud * */ public class GetTypeByHead { // 緩存文件頭信息-文件頭信息 public static final HashMap<String, String> mFileTypes = new HashMap<String, String>(); static { // images mFileTypes.put("FFD8FF", "jpg"); mFileTypes.put("89504E47", "png"); mFileTypes.put("47494638", "gif"); mFileTypes.put("49492A00", "tif"); mFileTypes.put("424D", "bmp"); // mFileTypes.put("41433130", "dwg"); // CAD mFileTypes.put("38425053", "psd"); mFileTypes.put("7B5C727466", "rtf"); // 日記本 mFileTypes.put("3C3F786D6C", "xml"); mFileTypes.put("68746D6C3E", "html"); mFileTypes.put("44656C69766572792D646174653A", "eml"); // 郵件 mFileTypes.put("D0CF11E0", "doc"); mFileTypes.put("5374616E64617264204A", "mdb"); mFileTypes.put("252150532D41646F6265", "ps"); mFileTypes.put("255044462D312E", "pdf"); mFileTypes.put("504B0304", "docx"); mFileTypes.put("52617221", "rar"); mFileTypes.put("57415645", "wav"); mFileTypes.put("41564920", "avi"); mFileTypes.put("2E524D46", "rm"); mFileTypes.put("000001BA", "mpg"); mFileTypes.put("000001B3", "mpg"); mFileTypes.put("6D6F6F76", "mov"); mFileTypes.put("3026B2758E66CF11", "asf"); mFileTypes.put("4D546864", "mid"); mFileTypes.put("1F8B08", "gz"); mFileTypes.put("4D5A9000", "exe/dll"); mFileTypes.put("75736167", "txt"); } /** * 根據(jù)文件路徑獲取文件頭信息 * * @param filePath * 文件路徑 * @return 文件頭信息 */ public static String getFileType(String filePath) { System.out.println(getFileHeader(filePath)); System.out.println(mFileTypes.get(getFileHeader(filePath))); return mFileTypes.get(getFileHeader(filePath)); } /** * 根據(jù)文件路徑獲取文件頭信息 * * @param filePath * 文件路徑 * @return 文件頭信息 */ public static String getFileHeader(String filePath) { FileInputStream is = null; String value = null; try { is = new FileInputStream(filePath); byte[] b = new byte[4]; /* * int read() 從此輸入流中讀取一個數(shù)據(jù)字節(jié)。 int read(byte[] b) 從此輸入流中將最多 b.length * 個字節(jié)的數(shù)據(jù)讀入一個 byte 數(shù)組中。 int read(byte[] b, int off, int len) * 從此輸入流中將最多 len 個字節(jié)的數(shù)據(jù)讀入一個 byte 數(shù)組中。 */ is.read(b, 0, b.length); value = bytesToHexString(b); } catch (Exception e) { } finally { if (null != is) { try { is.close(); } catch (IOException e) { } } } return value; } /** * 將要讀取文件頭信息的文件的byte數(shù)組轉(zhuǎn)換成string類型表示 * * @param src * 要讀取文件頭信息的文件的byte數(shù)組 * @return 文件頭信息 */ private static String bytesToHexString(byte[] src) { StringBuilder builder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } String hv; for (int i = 0; i < src.length; i++) { // 以十六進制(基數(shù) 16)無符號整數(shù)形式返回一個整數(shù)參數(shù)的字符串表示形式,并轉(zhuǎn)換為大寫 hv = Integer.toHexString(src[i] & 0xFF).toUpperCase(); if (hv.length() < 2) { builder.append(0); } builder.append(hv); } System.out.println(builder.toString()); return builder.toString(); } public static void main(String[] args) throws Exception { final String fileType = getFileType("D:\\Ry4S_JAVA.dll"); System.out.println(fileType); } }
總結(jié)
以上所述是小編給大家介紹的SpringBoot文件上傳控制及Java 獲取和判斷文件頭信息,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Spring中的@PropertySource注解源碼詳細解析
這篇文章主要介紹了Spring中的@PropertySource注解源碼詳細解析,@PropertySource注解,標(biāo)注在配置類@Configuration上面,下面主要分析一下@PropertySource注解的處理過程,也就是怎么把配置信息從.properies文件放到environment中的,需要的朋友可以參考下2024-01-01關(guān)于Logback+MyBatis日志輸出問題的一些思考
這篇文章主要介紹了關(guān)于Logback+MyBatis日志輸出問題的一些思考,具有很好的參考價值,希望對大家有所幫助,2023-09-09SpringBoot實現(xiàn)識別圖片中的身份證號與營業(yè)執(zhí)照信息
這篇文章主要為大家詳細介紹了SpringBoot如何實現(xiàn)識別圖片中的身份證號與營業(yè)執(zhí)照信息,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2024-01-01springboot+springsecurity如何實現(xiàn)動態(tài)url細粒度權(quán)限認(rèn)證
這篇文章主要介紹了springboot+springsecurity如何實現(xiàn)動態(tài)url細粒度權(quán)限認(rèn)證的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java構(gòu)造函數(shù)與普通函數(shù)用法詳解
本篇文章給大家詳細講述了Java構(gòu)造函數(shù)與普通函數(shù)用法以及相關(guān)知識點,對此有興趣的朋友可以參考學(xué)習(xí)下。2018-03-03Springboot過濾器禁止ip頻繁訪問功能實現(xiàn)
這篇文章主要介紹了Springboot過濾器禁止ip頻繁訪問功能實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04