日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【SpringBoot学习】35、SpringBoot 简易文件服务器

發布時間:2023/12/16 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SpringBoot学习】35、SpringBoot 简易文件服务器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • SpringBoot 簡易文件服務器
    • 確定需求
    • 核心技術
    • html 上傳:文件上傳
    • html 上傳:多文件上傳
    • html 上傳:圖片上傳 - 壓縮
    • ajax 上傳:FormData 上傳
    • 其他:將指定文件夾打包為 zip
    • 其他:生成二維碼
    • 常用:下載文件
    • 工具類:FileUtils
    • 工具類:QrCodeUtils
  • 微信公眾號

SpringBoot 簡易文件服務器

確定需求

首先,需求分析是核心一點,明白我們需要做成什么效果,再去想使用什么手段實現,當然,這里實現的核心工鞥就是對文件的操作:上傳、下載、壓縮、打包等

項目源碼

核心技術

  • 框架基礎:采用 spring boot 2.2.6.RELEASE,因為幾乎零配置文件,使用起來更加方便
  • 項目基礎:采用 apache-maven-3.6.0,使用坐標極大的簡化了 jar 的配置與安裝
  • 實體插件:采用 lombok,這個插件能使用注解的形式構建實體類相關的各種操作
  • 圖像壓縮:采用 Thumbnailator,目前網上算是比較用的普遍的圖片壓縮工具
  • json 序列化:采用 fastjson,序列化工具使用 alibaba 提供的工具類
  • 二維碼工具:采用 zxing,谷歌提供的生成二維碼的工具類
  • 文件操作必備的依賴:commons-io、commons-codec

html 上傳:文件上傳

html 的表單上傳文件,應該是開發中所有人接觸的第一種上傳方法,首先我們準備一個 form 表單,并設置對應的上傳路徑,表單中有一個 input 屬性,type 類型為 file 的輸入框,然后設置一個提交按鈕即可

<form method="POST" action="/upload" enctype="multipart/form-data"><input type="file" name="file"/><br/><br/>文件夾名稱:<input type="text" name="folder" value="upload"/><br/><br/><input type="submit" value="Submit"/> </form>

相對應的,后臺接收這個請求中的 file 對象,和 folder 參數,參數說明:

參數類型默認值說明
filefileinput 輸入框所選取的文件對象
foldertextupload存放服務器的文件夾

接收并處理請求,我這里將所有的代碼放在 serviceImpl 中編寫,因為 controller 控制層理論上只做控制處理,沒有邏輯業務

@ApiOperation("文件上傳")@PostMapping("/upload")public ResponseResult upload(@RequestParam("file") MultipartFile file,@RequestParam(value = "folder", defaultValue = "default") String folder) {return ResponseResult.success(fileService.upload(file, folder));}

service 接口層返回了一個 string 字符串類型,實際上就是上傳成功后返回的訪問路徑

String upload(MultipartFile file, String folder);

serviceImpl 實現類中處理請求分為三個階段:驗證參數、處理文件、返回訪問路徑

@Overridepublic String upload(MultipartFile file, String folder) {if (file.isEmpty()) {throw new FileVerifyException(FileEnums.NOT_FOUND.getInfo());}return FileUtils.upload(file, folder).getRelativePath();}

這里我們看到最后使用工具類 FileUtils 處理文件,工具類的內容我就不一步步分析了,其中涉及了異常處理、常量配置等,不做過多的介紹

html 上傳:多文件上傳

對于前端來書,多文件上傳與單文件上傳的區別在于,數量上的不同,選取多個文件,我們可以通過 input 的 multiple="multiple"屬性控制是否可以多選

<form method="POST" action="/uploadMore" enctype="multipart/form-data"><input type="file" name="file" multiple="multiple"/><br/><br/>文件夾名稱:<input type="text" name="folder" value="uploadFile"/><br/><br/><input type="submit" value="Submit"/> </form>

參數說明:

參數類型默認值說明
filefile增加了 multiple="multiple"之后,選擇多個文件實際上為一個數組對象
foldertextupload存放服務器的文件夾

接收并處理請求,我這里將所有的代碼放在 serviceImpl 中編寫,因為 controller 控制層理論上只做控制處理,沒有邏輯業務

@ApiOperation("多文件上傳")@PostMapping("/uploadMore")public ResponseResult uploadMore(@RequestParam("file") MultipartFile[] files,@RequestParam(value = "folder", defaultValue = "default") String folder) {return ResponseResult.success(fileService.uploadMore(files, folder));}

service 接口層返回了一個 string 字符串類型,實際上就是上傳成功后返回的訪問路徑,多個路徑之間使用“,”分隔開

String uploadMore(MultipartFile[] files, String folder);

serviceImpl 實現類中處理請求分為三個階段:驗證參數、處理文件、返回訪問路徑

@Overridepublic String uploadMore(MultipartFile[] files, String folder) {if (files.length == 0) {throw new FileVerifyException(FileEnums.NOT_FOUND.getInfo());}List<String> list = new ArrayList<>();for (MultipartFile file : files) {list.add(FileUtils.upload(file, folder).getRelativePath());}if (CollectionUtils.isEmpty(list)) {throw new FileSaveException(FileEnums.SAVE_ERROR.getInfo());}return StringUtils.join(list, FilePathConst.SEPARATOR);}

我這里多文件上傳實際上是遍歷文件單個上傳,然后拼接返回值,如果有更多的辦法,還請連一下作者喲

html 上傳:圖片上傳 - 壓縮

圖片上傳并且壓縮,這個是非常常見的功能需求,如果說客戶上傳一 10 張普通的圖片大小為 10M,1000 個客戶上傳的總大小為 10G 不到一點,對于服務器而言,存在一個的空間限制,而且訪問圖片的同時,由于圖片過大,導致加載速度過慢,這些問題都會導致客戶的體驗度下降,這里我們就可以考慮在不影響圖片清晰度的情況下,降低圖片占用的空間

<form method="POST" action="/uploadByThumbnail" enctype="multipart/form-data"><input type="file" name="file" multiple="multiple"/><br/><br/>文件夾名稱:<input type="text" name="folder" value="uploadByThumbnail"/><br/><br/>是否保存原圖:<input type="radio" name="saveOld" value="true" checked></label><input type="radio" name="saveOld" value="false"></label><br/><br/><input type="submit" value="Submit"/> </form>

參數說明:

參數類型默認值說明
filefileinput 輸入框所選取的文件對象
foldertextuploadByThumbnail存放服務器的文件夾
saveOldbooleantrue是否保存原圖

相對應的控制層處理和普通文件上傳是類似的,只是多了一個參數

@ApiOperation("圖片上傳并壓縮")@PostMapping("/uploadByThumbnail")public ResponseResult uploadByThumbnail(@RequestParam("file") MultipartFile[] files,@RequestParam(value = "folder", defaultValue = "default") String folder,@RequestParam(value = "saveOld", defaultValue = "true") boolean saveOld) {return ResponseResult.success(fileService.uploadByThumbnail(files, folder, saveOld));}

service 接口同樣返回訪問路徑,多個路徑使用“,”隔開

String uploadByThumbnail(MultipartFile[] files, String folder, boolean saveOld);

serviceImpl 接口實現類處理請求

@Overridepublic String uploadByThumbnail(MultipartFile[] files, String folder, boolean saveOld) {if (files.length == 0) {throw new FileVerifyException(FileEnums.NOT_FOUND.getInfo());}List<String> list = new ArrayList<>();for (MultipartFile file : files) {list.add(FileUtils.uploadByThumbnail(file, folder, saveOld).getRelativePath());}if (CollectionUtils.isEmpty(list)) {throw new FileSaveException(FileEnums.SAVE_ERROR.getInfo());}return StringUtils.join(list, FilePathConst.SEPARATOR);}

多圖片上傳并壓縮也是同樣的道理,這里需要注意一點,比如我上傳兩個圖片,并設置為保存原圖,實際上服務器保存了 4 張圖片,服務器的返回值的格式為:

{"code": 200,"message": "OK","count": 0,"data": "/uploadByThumbnail/2020/04/19/95f3da7a-f41b-4767-a229-a64108898f9a.png|/uploadByThumbnail/2020/04/19/95f3da7a-f41b-4767-a229-a64108898f9a_thumbnail.png,/uploadByThumbnail/2020/04/19/4be30b69-3205-462d-9f10-c7e5e851f3bc.png|/uploadByThumbnail/2020/04/19/4be30b69-3205-462d-9f10-c7e5e851f3bc_thumbnail.png" }

解析返回值:首先我們通過“,”分隔開,得到每張圖片的處理結果,然后在使用“|”將返回結果分隔開,得到原圖的訪問路徑和壓縮圖片的訪問路徑

ajax 上傳:FormData 上傳

工作中實際上直接使用 html 上傳幾乎是沒有的,因為通常我們要將上傳成功返回的訪問路徑存入數據庫中,接下來就是怎么樣拿到上傳返回的信息,這里我們舉例通過 ajax 的 FormData 的方式上傳

FormData 的 API 文檔參考

先引入 jquery,最好還是自己下載到本地放入項目當中

<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

這里我們不需要表單了,直接給 input 綁定點擊事件即可

<input type="file" name="file" id="formDataUpload"/><br/><br/> 文件夾名稱:<input type="text" name="folder" value="ajax" id="formDataFolder"/><br/><br/> <input type="button" value="Submit" id="formDataButton"/>

然后監聽點擊事件,我們的上傳路徑直接使用“html 上傳:文件上傳”模塊時使用的即可,主要是拿到返回值

$('#formDataButton').on('click', function () {var formData = new FormData();formData.append("file", $('#formDataUpload')[0].files[0]);formData.append("folder", $.trim($('#formDataFolder').val()));$.ajax({url: '/upload',dataType: 'json',type: 'POST',data: formData,processData: false, // 使數據不做處理contentType: false, // 不要設置Content-Type請求頭success: function (res) {console.log(res);if (res.code == 200) {alert("上傳成功");} else {alert("上傳失敗");}},error: function (res) {console.log(res);}});});

請求完成之后,在控制臺即可知道返回的結果,使用訪問前綴拼接上訪問路徑即可實現訪問圖片

其他:將指定文件夾打包為 zip

這個案例是實際開發中作者遇到的問題,完整需求是:通過請求參數,生成 1 萬張二維碼,并下載二維碼,這里我們就需要將這 1 萬張二維碼壓縮,并生成 zip,然后返回一個下載路徑即可

首先準備一個表單

<form method="POST" action="/folderToZip">待壓縮的文件路徑:<input type="text" name="folderPath" /><br/><br/>壓縮后存放路徑:<input type="text" name="zipPath"/><br/><br/>壓縮后文件的名稱:<input type="text" name="fileName"/><br/><br/><input type="submit" value="Submit"/> </form>

參數說明:路徑都是相對于文件服務器的根目錄書寫的,例如:/uploadByThumbnail/2020/04/19,不用寫絕對路徑

參數類型默認值說明
folderPathstring待壓縮的文件路徑
zipPathstring壓縮后存放路徑
fileNamestring壓縮后文件的名稱

控制層直接將請求交個 service 處理

@ApiOperation("將指定文件夾打包為zip")@PostMapping("/folderToZip")public ResponseResult folderToZip(String folderPath, String zipPath, String fileName) {return ResponseResult.success(fileService.folderToZip(folderPath, zipPath, fileName));}

service 接口,同樣的返回打包完成之后的訪問路徑,使用訪問前綴拼接上訪問路徑可即可下載 zip 包

String folderToZip(String folderPath, String zipPath, String fileName);

serviceImpl 實現類直接調用工具類處理

@Overridepublic String folderToZip(String folderPath, String zipPath, String fileName) {boolean flag = FileUtils.folderToZip(folderPath, zipPath, fileName);if (flag) {return zipPath + File.separator + fileName + ".zip";}throw new FileSaveException(FileEnums.FILE_ZIP_ERROR.getInfo());}

其他:生成二維碼

生成二維碼也是很常見的需要,通常情況下,我們將一些信息存放于二維碼中,用戶直接掃碼即可讀取相關信息,一般情況下,信息都是經過加密處理的,比如說考試的試卷信息,每張試卷都是獨一無二的編號,存放于這個二維碼中,考慮安全性,是不能直接被掃碼查看的

<form method="POST" action="/createQrCode">文件夾名稱:<input type="text" name="folder" value="createQrCode"/><br/><br/>二維碼內容:<input type="text" name="content" value="測試二維碼內容"/><br/><br/><input type="submit" value="Submit"/> </form>

參數說明:

參數類型默認值說明
foldertextcreateQrCode存放服務器的文件夾
contentstring測試二維碼內容二維碼內容

控制層

@ApiOperation("生成二維碼")@PostMapping("/createQrCode")public ResponseResult createQrCode(@RequestParam(value = "content", defaultValue = "默認二維碼內容")String content,@RequestParam(value = "folder", defaultValue = "default") String folder) {return ResponseResult.success(fileService.createQrCode(content, folder));}

service 接口同樣是返回二維碼的訪問地址

String createQrCode(String content, String folder);

serviceImpl 通過谷歌提供的二維碼生成工具類生成二維碼,這里的工具類被再次封裝過

@Overridepublic String createQrCode(String content, String folder) {try {String datePath = FileUtils.getDatePath(folder, FileUtils.DATE_TYPE_SLASH);String fileName = String.valueOf(UUID.randomUUID()).concat(".jpg");// 詳情查看工具類,功能非常強大QrCodeUtils.encode(content, null, FilePathConst.SAVE_POSITION + datePath, fileName, false);return datePath + fileName;} catch (Exception e) {e.printStackTrace();throw new FileSaveException(FileEnums.QRCODE_CREATE_ERROR.getInfo());}}

常用:下載文件

下載文件時一個核心功能,有上傳一定有下載,毋庸置疑。當我們上傳文件的同時,為了避免文件名重復等為題,我們會給文件名重命名為隨機名字,比如我這里使用的 Java UUID 工具:

// 文件名 String fileName = String.valueOf(UUID.randomUUID());

那么問題來了,我下載的時候要指定文件名字,下面就是實現方式

<form method="POST" action="/downloadFile">文件路徑:<input type="text" name="filePath" value="/default/2020/04/12/1fee42a4-f902-488b-87c6-ca82ea6bc958.jpg"/><br/><br/>下載名稱:<input type="text" name="fileName" value="我是下載文件的名字.jpg"/><br/><br/><input type="submit" value="Submit"/> </form>

參數說明:

參數類型默認值說明
filePathstring/default/2020/04/12/1fee42a4-f902-488b-87c6-ca82ea6bc958.jpg訪問的相對路徑,我這里的默認值是方便測試,之前上傳的圖片的訪問地址
fileNamestring我是下載文件的名字.jpg下載保存的文件名

這里有個細節,很多網上的教程下載中文名字時會發生亂碼,我這一步故意設置為中文名字,實際上后臺已經解決了這個問題
controller 控制層接收請求

@ApiOperation("下載文件")@PostMapping("downloadFile")public void downloadFile(String filePath, String fileName, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {fileService.downloadFile(filePath, fileName, request, response);}

service 接口沒有返回值,因為我這里是下載文件

void downloadFile(String filePath, String fileName, HttpServletRequest request, HttpServletResponse response);

serviceImpl 實現調用工具類實現下載

@Overridepublic void downloadFile(String filePath, String fileName, HttpServletRequest request, HttpServletResponse response) {FileUtils.download(filePath, fileName, request, response);}

工具類:FileUtils

文件操作工具類

/*** 文件上傳工具類** @author Tellsea* @date 2019/8/20*/ @Slf4j public class FileUtils {public static final String DATE_TYPE_SLASH = "yyyy" + File.separator + "MM" + File.separator + "dd";public static FileInfo upload(MultipartFile file, String folder) {// 文件名String fileName = String.valueOf(UUID.randomUUID());// 文件類型String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf("."));// 時間文件夾String datePath = getDatePath(folder, DATE_TYPE_SLASH);// 相對路徑String relativePath = datePath.concat(fileName).concat(fileType);// 絕對路徑String destFile = FilePathConst.SAVE_POSITION.concat(datePath);File f = new File(destFile);if (!f.exists() && !f.isDirectory()) {f.mkdirs();}// 文件全路徑destFile = destFile.concat(fileName).concat(fileType);try {byte[] bytes = file.getBytes();Path path = Paths.get(destFile);Files.write(path, bytes);log.info("上傳成功...");log.info("相對路徑:{}", relativePath);log.info("絕對路徑:{}", destFile);return new FileInfo().setFileName(fileName).setFileType(fileType).setDatePath(datePath).setDestFile(destFile).setRelativePath(relativePath);} catch (Exception e) {throw new FileSaveException(FileEnums.SAVE_ERROR.getInfo());}}/*** 壓縮上傳** @param file* @param folder* @param saveOld 是否保存原圖* @return*/public static FileInfo uploadByThumbnail(MultipartFile file, String folder, boolean saveOld) {FileInfo fileInfo = upload(file, folder);try {File toFile;if (saveOld) {String path = FilePathConst.SAVE_POSITION.concat(fileInfo.getDatePath()).concat(fileInfo.getFileName()).concat(FilePathConst.THUMBNAIL_SUFFIX).concat(fileInfo.getFileType());toFile = new File(path);String newFilePath = fileInfo.getDatePath().concat(fileInfo.getFileName()).concat(FilePathConst.THUMBNAIL_SUFFIX).concat(fileInfo.getFileType());fileInfo.setRelativePath(fileInfo.getRelativePath().concat(FilePathConst.THUMBNAIL_SEPARATOR) + newFilePath);} else {toFile = new File(fileInfo.getDestFile());}Thumbnails.of(fileInfo.getDestFile()).imageType(BufferedImage.TYPE_INT_ARGB)// 指定圖片大小 0-1f 1f是原圖.scale(0.5f)// 圖片質量 0-1f 1f是原圖.outputQuality(0.8f).toFile(toFile);} catch (Exception e) {e.printStackTrace();throw new FileThumbnailsException(FileEnums.THUMBNAILS_ERROR.getInfo());}return fileInfo;}/*** 獲得保存路徑** @param folder* @param dateFormat* @return 例如:/aaa/2020/04/11/*/public static String getDatePath(String folder, String dateFormat) {String date = new SimpleDateFormat(dateFormat).format(new Date());StringBuffer path = new StringBuffer();path.append(File.separator).append(folder).append(File.separator).append(date).append(File.separator);return path.toString();}/*** 將指定文件夾打包** @param sourceFilePath :待壓縮的文件路徑* @param zipFilePath :壓縮后存放路徑* @param fileName :壓縮后文件的名稱* @return*/public static boolean folderToZip(String sourceFilePath, String zipFilePath, String fileName) {boolean flag = false;File sourceFile = new File(sourceFilePath);FileInputStream fis = null;BufferedInputStream bis = null;FileOutputStream fos = null;ZipOutputStream zos = null;if (!sourceFile.exists()) {throw new FileVerifyException("待壓縮的文件目錄:" + sourceFilePath + "不存在.");} else {try {File zipFile = new File(zipFilePath + File.separator + fileName + ".zip");if (zipFile.exists()) {zipFile.delete();}File[] sourceFiles = sourceFile.listFiles();if (null == sourceFiles || sourceFiles.length < 1) {throw new FileVerifyException("待壓縮的文件目錄:" + sourceFilePath + "里面不存在文件,無需壓縮.");} else {fos = new FileOutputStream(zipFile);zos = new ZipOutputStream(new BufferedOutputStream(fos));byte[] bufs = new byte[1024 * 10];for (int i = 0; i < sourceFiles.length; i++) {//創建ZIP實體,并添加進壓縮包ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());zos.putNextEntry(zipEntry);//讀取待壓縮的文件并寫進壓縮包里fis = new FileInputStream(sourceFiles[i]);bis = new BufferedInputStream(fis, 1024 * 10);int read = 0;while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {zos.write(bufs, 0, read);}}flag = true;}} catch (FileNotFoundException e) {e.printStackTrace();throw new RuntimeException(e);} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);} finally {//關閉流try {if (null != bis) {bis.close();}if (null != zos) {zos.close();}} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);}}}return flag;}/*** 得到圖片字節流 數組大小*/public static byte[] readStream(InputStream inStream) throws Exception {ByteArrayOutputStream outStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = -1;while ((len = inStream.read(buffer)) != -1) {outStream.write(buffer, 0, len);}outStream.close();inStream.close();return outStream.toByteArray();}/*** 將文件轉換成Byte數組** @param file* @return*/public static byte[] getBytesByFile(File file) {try {FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);byte[] b = new byte[1000];int n;while ((n = fis.read(b)) != -1) {bos.write(b, 0, n);}fis.close();byte[] data = bos.toByteArray();bos.close();return data;} catch (Exception e) {e.printStackTrace();}return null;}/*** MultipartFile轉File** @param param* @return*/public static File transfer(MultipartFile param) {if (!param.isEmpty()) {File file = null;try {InputStream in = param.getInputStream();file = new File(param.getOriginalFilename());OutputStream out = new FileOutputStream(file);int bytesRead = 0;byte[] buffer = new byte[8192];while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {out.write(buffer, 0, bytesRead);}in.close();out.close();return file;} catch (Exception e) {e.printStackTrace();return file;}}return null;}/*** 獲取指定文件的輸入流** @param logoPath 文件的路徑* @return*/public static InputStream getResourceAsStream(String logoPath) {return FileUtils.class.getResourceAsStream(logoPath);}/*** 下載文件** @param filePath 訪問路徑* @param fileName 下載文件名* @param request* @param response*/public static void download(String filePath, String fileName, HttpServletRequest request, HttpServletResponse response) {File file = new File(FilePathConst.SAVE_POSITION + filePath);if (file.exists()) {response.setHeader("content-type", "application/octet-stream");response.setContentType("application/octet-stream");// 下載文件能正常顯示中文try {response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}// 實現文件下載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);}} catch (Exception e) {throw new FileSaveException(FileEnums.DOWNLOAD_ERROR.getInfo());} finally {if (bis != null) {try {bis.close();} catch (IOException e) {e.printStackTrace();}}if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}} else {throw new FileSaveException(FileEnums.DOWNLOAD_NOT_FOUND_ERROR.getInfo());}}public static void main(String[] args) {String path = "D:\\Workspace\\IDEAWorkspace\\file-server\\file-static\\uploadByThumbnail\\2020\\04\\12";folderToZip(path, path, "test");} }

工具類:QrCodeUtils

生成二維碼工具類

/*** 二維碼生成工具類** @author user* @date 2018/12/5*/ public class QrCodeUtils {private static final String CHARSET = "utf-8";public static final String FORMAT = "JPG";/*** 二維碼尺寸*/private static final int QRCODE_SIZE = 300;/*** LOGO寬度*/private static final int LOGO_WIDTH = 60;/*** LOGO高度*/private static final int LOGO_HEIGHT = 60;/*** 生成二維碼** @param content 二維碼內容* @param logoPath logo地址* @param needCompress 是否壓縮logo* @return 圖片* @throws Exception*/public static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, CHARSET);hints.put(EncodeHintType.MARGIN, 1);BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);}}if (logoPath == null || "".equals(logoPath)) {return image;}// 插入圖片QrCodeUtils.insertImage(image, logoPath, needCompress);return image;}/*** 插入LOGO** @param source 二維碼圖片* @param logoPath LOGO圖片地址* @param needCompress 是否壓縮* @throws IOException*/private static void insertImage(BufferedImage source, String logoPath, boolean needCompress) throws IOException {InputStream inputStream = null;try {inputStream = FileUtils.getResourceAsStream(logoPath);Image src = ImageIO.read(inputStream);int width = src.getWidth(null);int height = src.getHeight(null);if (needCompress) {// 壓縮LOGOif (width > LOGO_WIDTH) {width = LOGO_WIDTH;}if (height > LOGO_HEIGHT) {height = LOGO_HEIGHT;}Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = tag.getGraphics();// 繪制縮小后的圖g.drawImage(image, 0, 0, null);g.dispose();src = image;}// 插入LOGOGraphics2D graph = source.createGraphics();int x = (QRCODE_SIZE - width) / 2;int y = (QRCODE_SIZE - height) / 2;graph.drawImage(src, x, y, width, height, null);Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);graph.setStroke(new BasicStroke(3f));graph.draw(shape);graph.dispose();} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);} finally {if (inputStream != null) {inputStream.close();}}}/*** 生成二維碼(內嵌LOGO)* 二維碼文件名隨機,文件名可能會有重復** @param content 內容* @param logoPath LOGO地址* @param destPath 存放目錄* @param needCompress 是否壓縮LOGO* @throws Exception*/public static String encode(String content, String logoPath, String destPath, boolean needCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, needCompress);mkdirs(destPath);String fileName = new Random().nextInt(99999999) + "." + FORMAT.toLowerCase();ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));return fileName;}/*** 生成二維碼(內嵌LOGO)* 調用者指定二維碼文件名** @param content 內容* @param logoPath LOGO地址* @param destPath 存放目錄* @param fileName 二維碼文件名* @param needCompress 是否壓縮LOGO* @throws Exception*/public static String encode(String content, String logoPath, String destPath, String fileName, boolean needCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, needCompress);mkdirs(destPath);fileName = fileName.substring(0, fileName.indexOf(".") > 0 ? fileName.indexOf(".") : fileName.length())+ "." + FORMAT.toLowerCase();ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));return fileName;}/*** 當文件夾不存在時,mkdirs會自動創建多層目錄,區別于mkdir.* (mkdir如果父目錄不存在則會拋出異常)** @param destPath 存放目錄*/public static void mkdirs(String destPath) {File file = new File(destPath);if (!file.exists() && !file.isDirectory()) {file.mkdirs();}}/*** 生成二維碼(內嵌LOGO)** @param content 內容* @param logoPath LOGO地址* @param destPath 存儲地址* @throws Exception*/public static String encode(String content, String logoPath, String destPath) throws Exception {return QrCodeUtils.encode(content, logoPath, destPath, false);}/*** 生成二維碼** @param content 內容* @param destPath 存儲地址* @param needCompress 是否壓縮LOGO* @throws Exception*/public static String encode(String content, String destPath, boolean needCompress) throws Exception {return QrCodeUtils.encode(content, null, destPath, needCompress);}/*** 生成二維碼** @param content 內容* @param destPath 存儲地址* @throws Exception*/public static String encode(String content, String destPath) throws Exception {return QrCodeUtils.encode(content, null, destPath, false);}/*** 生成二維碼(內嵌LOGO)** @param content 內容* @param logoPath LOGO地址* @param output 輸出流* @param needCompress 是否壓縮LOGO* @throws Exception*/public static void encode(String content, String logoPath, OutputStream output, boolean needCompress)throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, needCompress);ImageIO.write(image, FORMAT, output);}/*** 生成二維碼** @param content 內容* @param output 輸出流* @throws Exception*/public static void encode(String content, OutputStream output) throws Exception {QrCodeUtils.encode(content, null, output, false);} }

微信公眾號

總結

以上是生活随笔為你收集整理的【SpringBoot学习】35、SpringBoot 简易文件服务器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。