Springboot檔案上傳下載
阿新 • • 發佈:2020-08-06
Springboot檔案上傳下載
檔案的上傳操作
前端程式碼
<form action="http://localhost:8091/file" method="post" enctype="multipart/form-data"> <input name="fileImage" type="file" /> <input type="submit" value="提交"/> </form>
服務端controller
@RequestMapping("/upload") public String file(MultipartFile fileImage) { String fileDirPath = "D:/images"; // 存放位置 File dirFile = new File(fileDirPath); // 判斷檔案目錄是否存在 if (!dirFile.exists()) { // 如果目錄沒有, 則應該新建目錄 dirFile.mkdir(); } // 準備檔案上傳路徑, 路徑 + 檔名稱 String fileName = fileImage.getOriginalFilename(); // 獲取檔名 File realFile = new File(fileDirPath + "/" + fileName); // 儲存磁碟路徑 + 檔名拼接 // 將位元組資訊輸出到檔案中 try { fileImage.transferTo(realFile); // 儲存到指定的路徑 return "檔案上傳成功"; } catch (IOException e) { e.printStackTrace(); return "檔案上傳失敗"; } }
檔案下載操作
下載操作也是非常的簡單, 我們只需要用流的形式返回到客戶端即可
別看長, 其實沒多少程式碼
@RequestMapping("/download") @ResponseBody public String downloadFile(HttpServletResponse response) { String fileName = "aaa.txt";// 設定檔名,即使用者下載得到檔案的名字(可以和磁碟中的檔名不同) if (fileName != null) { //設定檔案路徑 String filePath = "D:/file/001.txt"; // 要下載的檔案位置 File file = new File(filePath); if (file.exists()) { // 關於: application/octet-stream // 1、只能提交二進位制,而且只能提交一個二進位制,如果提交檔案的話,只能提交一個檔案,後臺接收引數只能有一個,而且只能是流(或者位元組陣列) // 2、屬於HTTP規範中Content-Type的一種 // 3、很少使用 response.setContentType("application/octet-stream"); // response.setHeader("content-type", "application/octet-stream"); // 也可以這樣寫 response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);// 設定檔名 byte[] buffer = new byte[1024]; FileInputStream fis = null; BufferedInputStream bis = null; try { fis = new FileInputStream(file); bis = new BufferedInputStream(fis); OutputStream os = response.getOutputStream(); int i = bis.read(buffer); while (i != -1) { os.write(buffer, 0, i); i = bis.read(buffer); } System.out.println("success"); // 下載成功返回資訊 } catch (Exception e) { e.printStackTrace(); } finally { // 關閉流 if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } } return null; // 下載失敗返回資訊 }
擴充套件: 上傳圖片並校驗
上傳圖片是經常有的操作, 所以在上傳圖片的時候也要對檔案進行校驗, 防止不符合規範的檔案或者偽裝的木馬病毒等, 例如:
- 校驗檔案的有效性
- 校驗檔案是否為惡意程式
- 提高使用者簡餐圖片的效率 分目錄儲存
- 為了防止重名圖片的提交 自定義檔名
- 實現圖片的物理上傳
- 準備一個訪問的虛擬路徑
Controller編寫
@Autowarld
private FileService fileService;
@RequestMapping("/pic/upload")
public ImageVO upload(MultipartFile uploadFile) {
return fileService.upload(uploadFile); // 呼叫service進行儲存圖片
}
Service編寫(介面略)
service類-結構
@Service
public class FileServiceImpl implements FileService {
@Override
public ImageVO upload(MultipartFile uploadFile) {
}
}
1.校驗檔案字尾
service中定義一個localDirPath靜態變數, 用於儲存支援的圖片你字尾, 例如:
private static Set<String> imageTypeSet = new HashSet<>();
static {
imageTypeSet.add(".jps");
imageTypeSet.add(".png");
imageTypeSet.add(".gif");
imageTypeSet.add("/bmp");
//.....其他省略
}
upload方法中
// 1. 圖片的型別 (1) 利用正則表示式 (2) 利用集合的方式進行校驗Set 資料是否存在即可
String fileName = uploadFile.getOriginalFilename();
// 獲取字尾 並轉為全小寫
String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
if (!imageTypeSet.contains(fileType)) { // 如果字尾沒在集合中, 則上傳失敗
return ImageVO.fail();
}
2.檢驗是否為圖片
upload方法中
// 2. 如何判斷檔案是否為惡意程式, 是否有圖片的屬性
// 2.1 將上傳檔案型別利用圖片API進行轉化
try {
BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
// 2.2 校驗是否有圖片的特有屬性 高度, 寬度
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
// 2.3 校驗寬度和高度是否有值
if (width == 0 || height == 0) {
return ImageVO.fail();
}
} catch (IOException e) {
e.printStackTrace();
return ImageVO.fail();
}
3.分目錄儲存
service中定義屬性, 表示檔案儲存的位置根路徑
private String localDirPath = "D:/images"; // 定義本地磁碟目錄
upload方法中
// 3. 實現分目錄儲存:
// 方案1: 利用hash之後每隔2-3位擷取之後拼接
// 方案2: 以時間為單位進行分割 /yyyy/MM/dd/ 這裡使用方案2, 方案1自行腦補
// 3.1 利用工具的API將時間轉化為執行的格式
String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
// 3.2 動態生成檔案目錄 2部分=根目錄+時間目錄
String localDir = localDirPath + datePath;
// 3.3 判斷目錄是否存在, 如果不存在則新建目錄
File dirFile = new File(localDir);
if (!dirFile.exists()) {
dirFile.mkdirs(); // 如果不存在, 則新建目錄
}
4.自定義檔名稱
使用UUID自定義名稱
//4. 防止檔案重名, 需要自定義檔名稱 UUID
//4.1 生成uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
//4.2動態生成檔名稱
String uuidFileName = uuid + fileType;
5.儲存上傳的檔案
// 5. 實現檔案的上傳
String realFilePath = localDir + uuidFileName;
// 5.1 封裝檔案的真實物件
File imageFile = new File(realFilePath);
// 5.1 實現檔案的儲存
try {
uploadFile.transferTo(imageFile);
} catch (IOException e) {
e.printStackTrace();
return ImageVO.fail();
}