SpringBoot整合Minio實(shí)現(xiàn)圖片上傳功能
minio服務(wù)器
minio服務(wù)器主要功能:保存文件【可以圖片、ppt、xsl】
1、MinIo簡(jiǎn)介
Minio 是個(gè)基于 Golang 編寫(xiě)的開(kāi)源對(duì)象存儲(chǔ)套件,雖然輕量,卻擁有著不錯(cuò)的性能。
官網(wǎng)地址:MinIO | High Performance, Kubernetes Native Object Storage
中文官網(wǎng)地址:http://www.minio.org.cn
中文文檔對(duì)應(yīng)的是上個(gè)版本,新版本中有些內(nèi)容已發(fā)生了變化,所以最好是看英文文檔。何為對(duì)象存儲(chǔ)?
對(duì)象存儲(chǔ)服務(wù)( Object Storage Service,OSS )是一種海量、安全、低成本、高可靠的云存儲(chǔ)服務(wù),適合存放任意類(lèi)型的文件。容量和處理能力彈性擴(kuò)展,多種存儲(chǔ)類(lèi)型供選擇,全面優(yōu)化存儲(chǔ)成本。
對(duì)于中小型企業(yè),如果不選擇存儲(chǔ)上云,那么 Minio 是個(gè)不錯(cuò)的選擇,麻雀雖小,五臟俱全。
2、安裝MinIo
a、下載安裝
Windows 版下載地址:windows-amd64 版按慣例,我們將下載的 minio.exe 放在 C:\ProgramFiles\MinIO 下,因此,MINIO_HOME 就是 C:\ProgramFiles\MinIO
b、安裝minio
1、下載 MinIO
安裝wget: yum -y install wget #由于需要用到wget命令,所以要先安裝wget 創(chuàng)建minio目錄: mkdir -p /usr/local/minio mkdir -p /usr/local/minio/bin mkdir -p /usr/local/minio/data 進(jìn)入/usr/local/minio/bin執(zhí)行如下命令: wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio 賦予它可執(zhí)行權(quán)限: 進(jìn)入到/usr/local/minio/bin中執(zhí)行如下命令 chmod +x minio
在usr/local下創(chuàng)建minio文件夾,并在minio文件里面創(chuàng)建bin和data目錄,把下載好的minio文件拷貝到bin目錄里面
2、將 minio 添加成 Linux 的服務(wù)
cat > /etc/systemd/system/minio.service << EOF [Unit] Description=Minio Wants=network-online.target After=network-online.target AssertFileIsExecutable=/usr/local/minio/bin/minio [Service] WorkingDirectory=/usr/local/minio/ PermissionsStartOnly=true ExecStart=/usr/local/minio/bin/minio server /usr/local/minio/data ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target EOF
這樣就可以使用 systemctl 啟停 minio
systemctl start minio # 啟動(dòng) systemctl stop minio # 停止 systemctl enable minio #設(shè)置自動(dòng)開(kāi)啟 systemctl status minio # 查看服務(wù)運(yùn)行狀態(tài)
c、啟動(dòng)運(yùn)行
輸入用戶(hù)名/密碼 minioadmin/minioadmin 可以進(jìn)入 web 管理系統(tǒng):
d、創(chuàng)建桶
剛打開(kāi)的時(shí)候,是沒(méi)有bucket桶,可以手動(dòng)或者通過(guò)java代碼來(lái)創(chuàng)建一個(gè)桶。
創(chuàng)建的桶默認(rèn)的權(quán)限時(shí)private私有的,外部不能訪問(wèn),你可以修改桶的屬性,點(diǎn)擊manage,找到Access Policy,修改權(quán)限為public即可。
e、上傳文件到桶
f、關(guān)停 MinIO
通過(guò)命令行啟動(dòng) MioIO 后,命令行窗口就被占用了。關(guān)閉命令行窗口即關(guān)閉 MioIO ,也可以使用 ctrl + c 關(guān)閉
3、Springboot整合minio
添加minio整合所需的依賴(lài)
com.squareup.okhttp3 okhttp 4.8.1 io.minio minio 8.3.9
設(shè)置minio服務(wù)器信息
#minio配置 minio: endpoint: http://127.0.0.1:9000 accesskey: minioadmin secretKey: minioadmin
創(chuàng)建minion配置類(lèi)
/** * minio配置類(lèi) */ @Configuration @Data @ConfigurationProperties(prefix = “minio”) public class MinIoConfig { private String endpoint; private String accesskey; private String secretKey; /** * 創(chuàng)建MinioClient對(duì)象 * @return * @throws Exception */ @Bean public MinioClient minioClient() throws Exception { return MinioClient.builder().endpoint(endpoint) .credentials(accesskey, secretKey).build(); } }
測(cè)試整合結(jié)果
4、案例:用戶(hù)頭像上傳
文件上傳是日常項(xiàng)目中非常常規(guī)且常用的一個(gè)功能。主要的功能就是將客戶(hù)端的文件保存到服務(wù)器,以便于資源的“瀏覽”。怎么實(shí)現(xiàn)文件上傳呢?SpringMvc中提供了對(duì)應(yīng)的文件上傳解析器,按照給定要求,在SpringMvc的環(huán)境下,我們可以很方便的實(shí)現(xiàn)上傳功能。
文件上傳注意事項(xiàng)
form 表單的 enctype 取值必須是:multipart/form-data(默認(rèn)值是:application/x-www-form-urlencoded)
method 屬性取值必須是 post
提供一個(gè)文件選擇域,HTML5原生html中,利用
不過(guò),元素file標(biāo)簽,外觀單一,企業(yè)級(jí)應(yīng)用中更多的會(huì)選擇使用外觀更加豐富的一些“組件”,比如在element-ui的el-upload組件
el-upload上傳組件常用屬性
<el-upload class="avatar-uploader" action="#" :show-file-list="false" :before-upload="beforeAvatarUpload" :http-request="doUploadImage"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload>
文件上傳組件常用屬性
- action:設(shè)置文件上傳控制器url地址,屬于同步請(qǐng)求提交方式。必備屬性
- http-request:設(shè)置實(shí)現(xiàn)上傳請(qǐng)求發(fā)送的自定義函數(shù)名,若要實(shí)現(xiàn)自定義上傳方式,必須使用http-requeset
- :before-upload:處理圖片上傳過(guò)程的鉤子,該屬性處理圖片上傳之前的功能。其值設(shè)置一個(gè)函數(shù),參考上述案例代碼:可以判斷上傳文件的格式和大小
axios.post提交上傳請(qǐng)求
因?yàn)槲募蟼鞯母袷奖仨毷牵簃ultipart/formdata格式,所以axios.post處理文件上傳時(shí),參數(shù)較以前的使用,略有變化,具體代碼參考如下:
doUpload(file){//file 獲取用戶(hù)選擇封面圖片 console.log("file",file.file); //將用戶(hù)選擇的圖片內(nèi)容封裝為formdata類(lèi)型,才能交給控制器處理 let formData=new FormData(); formData.append("face",file.file); axios.post("/user/do-upload",formData,{contentType:'multipart/form-data'}) .then(resp=>{ if(resp.data.status===200){ alert("文件上傳成功"+resp.data.msg); }else{ alert("文件上傳失敗"); } });
代碼解讀
FormData是JavaScript提供的一個(gè)對(duì)象類(lèi)型,作用封裝multipart/form-data格式數(shù)據(jù)。 formData對(duì)象的append()方法,可以以key:value格式存入數(shù)據(jù),控制器在后臺(tái)以key獲取對(duì)應(yīng)的值 contentType:'multipart/form-data'設(shè)置axios.post提交數(shù)據(jù)格式。 因?yàn)閍xios.post默認(rèn)提交格式是jsonstring,此處需要手動(dòng)顯式設(shè)置數(shù)據(jù)提交格式:contentType:'multipart/form-data'
Controller控制器后端處理上傳請(qǐng)求
Springmvc處理文件上傳請(qǐng)求時(shí),因?yàn)檎?qǐng)求體提交數(shù)據(jù)的格式不再是傳統(tǒng)的jsonstring或querystring格式,所以,控制器在處理上傳請(qǐng)求前,需要先配置文件上傳解析器。具體流程如下所示:
pom.xml導(dǎo)入文件解析器依賴(lài)
commons-fileupload commons-fileupload 1.4 commons-io commons-io 2.10.0
pplication.yml配置文件上傳解析器
Spring: servlet: multipart: max-file-size: 30MB #單個(gè)文件的最大上限 max-request-size: 60MB #單個(gè)請(qǐng)求的文件總大小上限
Controller處理上傳請(qǐng)求
@PostMapping(“/do-upload”) public ResponseResult doUploadImage( @RequestParam(value = “aa”,required = true,defaultValue = “”) MultipartFile image ) { log.info(“用戶(hù)提交的圖書(shū):{}”,image); //保存文件到minio服務(wù)器即可 String bucketName=“woniu-mall”; //1-1 創(chuàng)建桶 minIoUtil.createBucket(bucketName); //1-2 上傳文件 String oldName = image.getOriginalFilename(); //文件名稱(chēng) String firstName = UUID.randomUUID().toString().replace(“-”, “”); //文件后綴名 String lastName = oldName.substring(oldName.lastIndexOf(“.”)); //新的文件名稱(chēng) String fileName=“goods/”+firstName+ lastName; minIoUtil.putObject(bucketName,image,fileName,image.getContentType()); //1-3 獲取外鏈 String objectUrl = minIoUtil.getObjectUrl(bucketName, fileName); return new ResponseResult(200,“上傳成功!”,objectUrl); }
處理上傳后的響應(yīng)結(jié)果
Minio操作工具類(lèi)
基于Springmvc整合Minio時(shí),我們?cè)贛inioConfig中注入過(guò)MinioClient對(duì)象,而MinioClient對(duì)象就是操作minio服務(wù)器的核心對(duì)象,該對(duì)象提供了在minio服務(wù)器上創(chuàng)建桶、上傳文件,分享外鏈給用戶(hù)使用的功能。為了便于日常的開(kāi)發(fā)使用,我們將這些功能封裝成MinioUtil工具類(lèi),開(kāi)發(fā)人員結(jié)合開(kāi)發(fā)需求,調(diào)用對(duì)應(yīng)方法完成需求即可。工具類(lèi)的具體代碼如下所示:
@Slf4j //日志管理工具 @Component public class MinIoUtil { @Autowired private MinioClient minioClient; /** * 創(chuàng)建桶 * @param bucketName 桶名 */ public void createBucket(String bucketName) { BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build(); MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build(); try { if (minioClient.bucketExists(bucketExistsArgs)) { return; } minioClient.makeBucket(makeBucketArgs); } catch (Exception e) { //跟sout作用一樣,在控制臺(tái)輸出程序執(zhí)行信息 log.error("創(chuàng)建桶失?。?, e.getMessage()); throw new RuntimeException(e); } } /** * 通過(guò) MultipartFile ,上傳文件 * * @param bucketName 存儲(chǔ)桶 * @param file 文件 * @param objectName 對(duì)象名(文件名)存入桶時(shí),文件新命名:唯一不重復(fù) * @param contentType 文件類(lèi)型 文件上傳時(shí)格式 */ public ObjectWriteResponse putObject(String bucketName, MultipartFile file, String objectName, String contentType) { try { //調(diào)用創(chuàng)建桶方法 createBucket(bucketName); //獲取文件輸入流 InputStream inputStream = file.getInputStream(); PutObjectArgs args = PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .contentType(contentType) .stream(inputStream, inputStream.available(), -1) .build(); return minioClient.putObject(args); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) { throw new RuntimeException(e); } } /** * 獲取?件外鏈 * * @param bucketName bucket名稱(chēng) * @param objectName ?件名稱(chēng) * @param expires 過(guò)期時(shí)間 <=7 * @param timeUnit 有效期時(shí)間單位 */ public String getObjectUrl(String bucketName, String objectName, Integer expires, TimeUnit timeUnit) { GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(objectName) .expiry(expires,timeUnit)// 單位:默認(rèn)是,秒 .build(); try { String url=minioClient.getPresignedObjectUrl(args); return getImgUrl(url); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | IOException | XmlParserException | ServerException e) { throw new RuntimeException(e); } } /** * 獲取?件外鏈 * * @param bucketName bucket名稱(chēng) * @param objectName ?件名稱(chēng) */ public String getObjectUrl(String bucketName, String objectName) { GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(objectName)// 單位:默認(rèn)是,秒 .build(); try { String url=minioClient.getPresignedObjectUrl(args); return getImgUrl(url); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | IOException | XmlParserException | ServerException e) { throw new RuntimeException(e); } } /** * 處理圖片上傳后外鏈地址 * 只獲得url端口號(hào)以后的內(nèi)容 * @param urlStr * @return */ private String getImgUrl(String urlStr){ if(urlStr.isEmpty()){ return ""; } Pattern pattern = Pattern.compile("\\?"); //通過(guò)正則找字符串中的? Matcher matcher = pattern.matcher(urlStr); //正則表達(dá)式比對(duì)器 if (matcher.find()){ int seartIndex = matcher.end(); //獲得?開(kāi)始的位置 if(seartIndex!=-1){ urlStr=urlStr.substring(0,seartIndex-1); } } Pattern pattern1 = Pattern.compile(":\\d{1,5}"); //通過(guò)正則找字符串中的端口 Matcher matcher1 = pattern1.matcher(urlStr); //正則表達(dá)式比對(duì)器 if (matcher1.find()){ int endIndex = matcher1.end(); //獲得正則表達(dá)式規(guī)則結(jié)束字符串的位置 if(endIndex!=-1){ return urlStr.substring(endIndex); } } return ""; } }
5、常見(jiàn)問(wèn)題
商品列表:表格圖片無(wú)法正常顯示問(wèn)題
用戶(hù)頭像顯示問(wèn)題:element組件中el-table默認(rèn)循環(huán)時(shí),沒(méi)有給每一行指定key,用于標(biāo)識(shí)數(shù)據(jù)渲染的位置,所以在使用el-avatar顯示圖片時(shí),會(huì)出現(xiàn)圖片url地址正確的情況下,圖片無(wú)法正常顯示問(wèn)題,
解決方案有以下兩種:
修改商品信息時(shí):設(shè)置圖片回顯
在商品信息管理時(shí),我們可能會(huì)對(duì)商品的封面照片進(jìn)行修改。那么當(dāng)我們點(diǎn)擊“修改”按鈕進(jìn)入到商品修改頁(yè)面時(shí),一般情況,需要默認(rèn)顯示商品“舊”圖片的信息。el-upload組件如何設(shè)置默認(rèn)顯示的圖片呢?在修改頁(yè)面初始化數(shù)據(jù)時(shí),給el-upload組件的imageUrl賦值即可完成
以上就是SpringBoot整合Minio實(shí)現(xiàn)圖片上傳功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Minio圖片上傳的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- minio的下載和springboot整合minio使用方法
- SpringBoot整合Minio實(shí)現(xiàn)文件上傳和讀取功能
- springboot整合minio的超詳細(xì)教程
- 可能是全網(wǎng)最詳細(xì)的springboot整合minio教程
- SpringBoot整合MinIO實(shí)現(xiàn)文件上傳的方法詳解
- Spring?Boot?3?整合?MinIO?實(shí)現(xiàn)分布式文件存儲(chǔ)的全過(guò)程
- SpringBoot+MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)方式
- Vue?+?SpringBoot?實(shí)現(xiàn)文件的斷點(diǎn)上傳、秒傳存儲(chǔ)到Minio的操作方法
- 在 Spring Boot 中集成 MinIO 對(duì)象存儲(chǔ)
相關(guān)文章
關(guān)于Java大整數(shù)運(yùn)算之BigInteger類(lèi)
這篇文章主要介紹了關(guān)于Java大整數(shù)運(yùn)算之BigInteger類(lèi),BigInteger提供高精度整型數(shù)據(jù)類(lèi)型及相關(guān)操作,所有操作中,都以二進(jìn)制補(bǔ)碼形式表示,需要的朋友可以參考下2023-05-05JAVA代碼設(shè)置selector不同狀態(tài)下的背景顏色
這篇文章主要介紹了JAVA代碼設(shè)置selector不同狀態(tài)下的背景顏色,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05springboot接收日期字符串參數(shù)與返回日期字符串類(lèi)型格式化
這篇文章主要介紹了springboot接收日期字符串參數(shù)與返回日期字符串類(lèi)型格式化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01fastjson對(duì)JSONObject中的指定字段重新賦值的實(shí)現(xiàn)
這篇文章主要介紹了fastjson對(duì)JSONObject中的指定字段重新賦值的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Java中的FileInputStream 和 FileOutputStream 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
FileInputStream 是文件輸入流,它繼承于InputStream。FileOutputStream 是文件輸出流,它繼承于OutputStream。接下來(lái)通過(guò)本文給大家介紹Java中的FileInputStream 和 FileOutputStream,需要的朋友可以參考下2017-05-05maven中心倉(cāng)庫(kù)OSSRH使用簡(jiǎn)介(推薦)
這篇文章主要介紹了maven中心倉(cāng)庫(kù)OSSRH使用簡(jiǎn)介,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Hibernate三種狀態(tài)和Session常用的方法
本文主要介紹了Hibernate三種狀態(tài)和Session常用的方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-03-03