- 資訊首頁(yè) > 互聯(lián)網(wǎng) > 經(jīng)驗分享 >
- 對象存儲搭建圖床教程:Spring Boot Vue Antd U
網(wǎng)上已經(jīng)一些運行不錯的圖床了,比如SM.MS https://sm.ms/,圖殼 https://imgkr.com,路過(guò)圖床 https://imgchr.com/,那為什么我們還要自己搭建圖床呢?一來(lái)是因為碼農總是喜歡折騰,二來(lái)是有了自己的圖床數據自己存儲更安全。那么接下來(lái)我們就搞起來(lái)。下面是演示地址,可以先看一下搭建完成的效果。https://xiaotuwo.github.io,點(diǎn)擊按鈕上傳圖片,完成以后可以復制鏈接和下載。
準備前端環(huán)境
編寫(xiě)前端代碼
到這里我們基礎環(huán)境就搭建完成了,下面就開(kāi)始編寫(xiě)前端的代碼。我們是以 sm.ms 作為原型進(jìn)行搭建。如下圖我們只編輯他的頭部,上傳部分和尾部。
成品形態(tài)如下,把 sm.ms 拖拽上傳圖片的交互設計改成了點(diǎn)擊上傳圖片,不過(guò)如果你想實(shí)現拖拽也是非常簡(jiǎn)單,下面是 antd 的樣式,換一個(gè)標簽即可。https://www.antdv.com/components/upload-cn/
頭部和尾部代碼非常簡(jiǎn)單,我們只講解上傳部分代碼。搭建好 vue 框架以后去上面提供的 antd 的網(wǎng)址里面找到 upload 控件,直接點(diǎn)擊復制自己喜歡的代碼樣式,粘貼到 content/index.vue 里面就可以了,然后修改 a-upload 的 action 為自己的服務(wù)器地址即可,本地測試就是http://localhost:8887/api/images/upload,下文中也有配套的服務(wù)端代碼。
vue 的語(yǔ)法就不具體展開(kāi)了,主要講解一個(gè)地方,handlePreview方法里面我添加了一個(gè)復制鏈接的邏輯,可以輕松的點(diǎn)擊預覽的時(shí)候復制圖片鏈接,這樣方便的把網(wǎng)址放入其他地方進(jìn)行使用。
his.$message.success('復制圖片鏈接成功'); document.addEventListener("copy", function copyCall(e) { e.preventDefault() e.clipboardData.setData("text/html", file.preview) e.clipboardData.setData("text/plain", file.preview) document.removeEventListener("copy", copyCall) })
到這里基本的前端的搭建完成了,可以直接查看源碼,https://github.com/xiaotuwo/xiaotuwo-client
服務(wù)器端環(huán)境準備
本文采用的是UCloud對象存儲產(chǎn)品 US3 進(jìn)行圖床搭建,目前 US3有 20G 的免費存儲和每個(gè)月20G 的免費流量,對于自用和起步還是足夠的。
復制下面的鏈接到瀏覽器訪(fǎng)問(wèn)查看 US3 官網(wǎng),首次進(jìn)入需要注冊,https://urlify.cn/YNNBNn,注冊完成以后,進(jìn)入控制臺創(chuàng )建 US3 空間。
進(jìn)入空間以后填寫(xiě)存儲名,私有空間和公開(kāi)空間都可以,我創(chuàng )建的是 xiaotuwo.cn-bj.ufileos.com 留存備用。
在 US3 控制臺創(chuàng )建令牌,主要是用來(lái)上傳,刪除圖片使用。
選擇好自己剛才創(chuàng )建的空間,設置年限點(diǎn)擊確定即可,記得一定要勾選令牌的權限。
點(diǎn)擊完成以后獲取到公鑰私鑰,復制備用
編寫(xiě)服務(wù)端代碼
服務(wù)端代碼主要分為三個(gè)部分
1、接收請求的 Controller
2、上傳圖片到 US3 的邏輯
3、返回內容處理
1、 編寫(xiě) Controller
使用 MultipartHttpServletRequest 接收到前端的 file 文件,調用 uCloudProvider 進(jìn)行上傳。
@PostMapping({"/api/files/upload"}) @ResponseBody public FileDTO upload(HttpServletRequest request) { FileDTO resultFileDTO = new FileDTO(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultipartFile file = multipartRequest.getFile("file"); long start = System.currentTimeMillis(); try { if (file == null) { resultFileDTO.setStatus("error"); } FileDTO fileDTO = uCloudProvider.uploadWithExpired(file.getInputStream(), file.getContentType(), Objects.requireNonNull(file.getOriginalFilename())); log.info("UPLOAD_FILE_EXPIRED|ip:{}|referer:{}|url:{}|cost:{}", getIpAddress(request), request.getHeader("referer"), fileDTO.getUrl(), System.currentTimeMillis() - start); executorService.submit(new UCloudScanner(fileDTO, uCloudProvider, executorService, 1)); resultFileDTO.setName(fileDTO.getName()); resultFileDTO.setUrl(fileDTO.getUrl()); resultFileDTO.setThumbUrl(fileDTO.getUrl()); resultFileDTO.setStatus("done"); } catch (Exception e) { log.error("UPLOAD_FILE_ERROR", e); resultFileDTO.setStatus("error"); } return resultFileDTO; }
2、上傳圖片到 US3 的邏輯
上傳 US3 主要是一些配置文件,我直接使用的 Maven 的 Filter 處理,配置文件在 pom.xml 里面,編譯的時(shí)候寫(xiě)入 application.properties
<id>dev</id> <properties> <server.port>8887</server.port> <ucloud.ufile.public-key>你的公鑰</ucloud.ufile.public-key> <ucloud.ufile.private-key>你的私鑰</ucloud.ufile.private-key> <ucloud.ufile.upload-domain-private>你的bucket名字.cn-bj.ufileos.com</ucloud.ufile.upload-domain-private> <ucloud.ufile.download-domain-private>你的bucket名字.cn-bj.ufileos.com</ucloud.ufile.download-domain-private> <ucloud.uaicensor.publicKey>鑒黃公鑰</ucloud.uaicensor.publicKey> <ucloud.uaicensor.privateKey>鑒黃私鑰</ucloud.uaicensor.privateKey> <ucloud.uaicensor.resourceId>鑒黃ID</ucloud.uaicensor.resourceId> <ucloud.uaicensor.url>http://api.uai.ucloud.cn/v1/image/scan</ucloud.uaicensor.url> </properties> <activation> <activeByDefault>true</activeByDefault> </activation>
我們會(huì )發(fā)現配置文件里面除了文件的配置還有一套鑒黃的配置,對的這個(gè)地方不是本文的重點(diǎn),但是圖床一定要有鑒黃的能力,具體的實(shí)現可以參考文章 通過(guò)UCloud AI內容審核UAI-Censor免費搭建鑒黃平臺教程
具體 US3 的邏輯代碼也是非常的簡(jiǎn)單,主要的邏輯就是上傳,使用私鑰和時(shí)間戳生成鏈接,顯示。
public FileDTO upload(InputStream fileStream, String mimeType, String fileName) { String generatedFileName; String[] filePaths = fileName.split("\."); if (filePaths.length > 1) { generatedFileName = UUID.randomUUID().toString() "." filePaths[filePaths.length - 1]; } else { throw new ErrorCodeException(ErrorCode.FILE_UPLOAD_FAIL); } long start = System.currentTimeMillis(); try { log.debug("UCloudProvider start upload file, filename : {}, time : {}", fileName, new Date()); ObjectAuthorization objectAuthorization = new UfileObjectLocalAuthorization(publicKey, privateKey); ObjectConfig config = new ObjectConfig(uploadDomainPrivate); PutObjectResultBean response = UfileClient.object(objectAuthorization, config) .putObject(fileStream, mimeType) .nameAs(generatedFileName) .toBucket(bucketNamePrivate) .setOnProgressListener((bytesWritten, contentLength) -> { }) .execute(); log.debug("UCloudProvider end upload file, filename : {}, time : {}, cost : {}", fileName, new Date(), System.currentTimeMillis() - start); if (response != null && response.getRetCode() == 0) { long start2 = System.currentTimeMillis(); log.debug("UCloudProvider start get url, filename : {}, time : {}", fileName, new Date()); String url = UfileClient.object(objectAuthorization, new ObjectConfig(downloadDomainPrivate)) .getDownloadUrlFromPrivateBucket(generatedFileName, bucketNamePrivate, 24 * 60 * 60) .createUrl(); log.debug("UCloudProvider end get url, filename : {}, time : {}, cost : {}", fileName, new Date(), System.currentTimeMillis() - start2); FileDTO fileDTO = new FileDTO(); fileDTO.setUrl(url.replace("http", "https")); fileDTO.setName(generatedFileName); return fileDTO; } else { log.debug("UCloudProvider end upload file, filename : {}, time : {}, cost : {}", fileName, new Date(), System.currentTimeMillis() - start); log.error("upload error,{}", response); throw new ErrorCodeException(ErrorCode.FILE_UPLOAD_FAIL); } } catch (UfileClientException | UfileServerException e) { log.debug("UCloudProvider end upload file, filename : {}, time : {}, cost : {}", fileName, new Date(), System.currentTimeMillis() - start); log.error("upload error,{}", fileName, e); throw new ErrorCodeException(ErrorCode.FILE_UPLOAD_FAIL); } }
3、 返回內容處理,這里也需要注意一下,為了配合 antd 的 upoad 控件,我們的 dto 如下
@Data public class FileDTO { private String name; private String status; private String url; private String thumbUrl; }
服務(wù)器端源碼訪(fǎng)問(wèn)
https://github.com/xiaotuwo/xiaotuwo-server
到這里就全部結束了,你學(xué)會(huì )了嗎?如果有任何問(wèn)題,可以到 US3 自己的官方論壇提問(wèn)https://uclub.ucloud.cn/invite/93
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站