Day6 - 头像存储与EasyExcel
文章目錄
- 一. 阿里云OSS存儲(chǔ)
- 1. 注冊(cè)并創(chuàng)建存儲(chǔ)空間
- 2. 獲取 key
- 3. 官方文檔
- 二. 頭像上傳后臺(tái)開(kāi)發(fā)
- 1. service-oss 模塊搭建
- 2. 后臺(tái)上傳代碼
- 三. nginx 請(qǐng)求轉(zhuǎn)發(fā)
- 1. nginx 基礎(chǔ)概念
- 2. 實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)
- 四. 頭像上傳前端代碼
- 1. 導(dǎo)入上傳文件模塊
- 2. 頭像上傳組件
- 五. EasyExcel的使用
- 1. 引入 pom 依賴
- 2. 寫操作
- 3. 讀操作
一. 阿里云OSS存儲(chǔ)
阿里云的對(duì)象存儲(chǔ) OSS 提供海量、安全、低成本、高可靠的云存儲(chǔ)服務(wù),很多公司都會(huì)使用它來(lái)進(jìn)行數(shù)據(jù)存儲(chǔ)。因此,我們將講師頭像存儲(chǔ)在這里。
1. 注冊(cè)并創(chuàng)建存儲(chǔ)空間
進(jìn)入阿里云官網(wǎng),注冊(cè)賬號(hào)登錄,并實(shí)名認(rèn)證。之后找到 OSS 存儲(chǔ):
進(jìn)入后點(diǎn)擊【立即開(kāi)通】,開(kāi)通成功后,按鈕變?yōu)椤竟芾砜刂婆_(tái)】,點(diǎn)擊后進(jìn)入下列頁(yè)面。點(diǎn)擊【創(chuàng)建 Buket】即可創(chuàng)建一個(gè)存儲(chǔ)空間:
點(diǎn)擊剛創(chuàng)建的 bucket 名稱,可以查看存儲(chǔ)的東西,或者上傳文件:
2. 獲取 key
在主頁(yè)面,有一個(gè)【Access Key】按鈕,點(diǎn)擊后按照要求獲取 key 供后續(xù)代碼使用:
3. 官方文檔
阿里云 OSS Java 使用官方文檔
(1)安裝
在pom.xml中添加:
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.0</version> </dependency>(2)使用代碼創(chuàng)建存儲(chǔ)空間
// Endpoint以杭州為例,其它Region請(qǐng)按實(shí)際情況填寫。 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // 阿里云主賬號(hào)AccessKey擁有所有API的訪問(wèn)權(quán)限,風(fēng)險(xiǎn)很高。強(qiáng)烈建議您創(chuàng)建并使用RAM賬號(hào)進(jìn)行API訪問(wèn)或日常運(yùn)維,請(qǐng)登錄 https://ram.console.aliyun.com 創(chuàng)建RAM賬號(hào)。 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>"; String bucketName = "<yourBucketName>";// 創(chuàng)建OSSClient實(shí)例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 創(chuàng)建存儲(chǔ)空間。 ossClient.createBucket(bucketName);// 關(guān)閉OSSClient。 ossClient.shutdown();(3)上傳文件流
// Endpoint以杭州為例,其它Region請(qǐng)按實(shí)際情況填寫。 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // 云賬號(hào)AccessKey有所有API訪問(wèn)權(quán)限,建議遵循阿里云安全最佳實(shí)踐,創(chuàng)建并使用RAM子賬號(hào)進(jìn)行API訪問(wèn)或日常運(yùn)維,請(qǐng)登錄 https://ram.console.aliyun.com 創(chuàng)建。 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>";// 創(chuàng)建OSSClient實(shí)例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 上傳文件流。 InputStream inputStream = new FileInputStream("<yourlocalFile>"); ossClient.putObject("<yourBucketName>", "<yourObjectName>", inputStream);// 關(guān)閉OSSClient。 ossClient.shutdown();二. 頭像上傳后臺(tái)開(kāi)發(fā)
1. service-oss 模塊搭建
(1)在 service 下右鍵選擇 New Module… 創(chuàng)建一個(gè)子模塊 service-oss;
(2)在 pom.xml 中添加 oss 依賴(版本信息在主模塊中已經(jīng)配置了):
(3)創(chuàng)建 application.properties 以及啟動(dòng)類文件:
#服務(wù)端口號(hào) server.port=8082#服務(wù)名 spring.application.name=service-oss #環(huán)境設(shè)置 spring.profiles.active=dev#阿里云 OSS #不同的服務(wù)器,地址不同 aliyun.oss.file.endpoint=oss-cn-beijing.aliyuncs.com aliyun.oss.file.keyid=LTAI4GEMTPi4AYWfHuxkiGA9 aliyun.oss.file.keysecret=ijJ10mCflSnbVc89V3zFIYT3zQqpze #bucket可以在控制臺(tái)創(chuàng)建,也可以使用java代碼創(chuàng)建 aliyun.oss.file.bucketname=guli-edu-avatar-2020要注意一點(diǎn),由于上述配置文件中不需要配置數(shù)據(jù)庫(kù)相關(guān)內(nèi)容,啟動(dòng)時(shí)會(huì)報(bào)錯(cuò),因此下面 @SpringBootApplication 注解中要加上 exclude = DataSourceAutoConfiguration.class
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @ComponentScan(basePackages = {"com.atguigu"}) public class OssApplication {public static void main(String[] args) {SpringApplication.run(OssApplication.class, args);} }2. 后臺(tái)上傳代碼
(1)獲取配置文件中的 OSS 各項(xiàng)值;
配置文件中的值可以通過(guò) @Value(${xxx}) 注解進(jìn)行獲取,創(chuàng)建一個(gè)Util類專門用于獲取配置文件中的值。但由于此時(shí)值是 private 的,所以需要將其賦值給一個(gè)public 對(duì)象??梢詫?shí)現(xiàn) InitializingBean 接口中的 afterPropertiesSet 方法,它在項(xiàng)目啟動(dòng)時(shí),獲取到值后即被調(diào)用。
注意這里不能直接定義 public 對(duì)象,再在它的上面加@Value注解,值會(huì)取不到。
@Component public class ConstantPropertiesUtil implements InitializingBean {@Value("${aliyun.oss.file.endpoint}")private String endPoint;@Value("${aliyun.oss.file.keyid}")private String keyId;@Value("${aliyun.oss.file.keysecret}")private String keySecret;@Value("${aliyun.oss.file.bucketname}")private String bucketName;public static String END_POINT;public static String KEY_ID;public static String KEY_SECRET;public static String BUCKET_NAME;@Overridepublic void afterPropertiesSet() throws Exception {END_POINT = endPoint;KEY_ID = keyId;KEY_SECRET = keySecret;BUCKET_NAME = bucketName;} }(2)創(chuàng)建 controler 和 service 類
我們是先創(chuàng)建了一個(gè) service 接口,再創(chuàng)建了它的一個(gè)實(shí)現(xiàn)類,
controller中的注入可以注入接口,也可以注入具體的實(shí)現(xiàn)類。(當(dāng)有多個(gè)實(shí)現(xiàn)類時(shí)只能注入實(shí)現(xiàn)類,否則會(huì)報(bào)錯(cuò)有多個(gè) bean 是 OssService 類型):
但是接口中只定義了方法:
public interface OssService {String uploadAvatar(MultipartFile file); }真正實(shí)現(xiàn)以及 @Service 注解都是在實(shí)現(xiàn)類上:
@Service public class OssServiceImpl implements OssService {@Overridepublic String uploadAvatar(MultipartFile file) {String endPoint = ConstantPropertiesUtil.END_POINT;String bucketName = ConstantPropertiesUtil.BUCKET_NAME;String keyId = ConstantPropertiesUtil.KEY_ID;String keySecret = ConstantPropertiesUtil.KEY_SECRET;// 創(chuàng)建OSSClient實(shí)例。OSS ossClient = new OSSClientBuilder().build(endPoint, keyId, keySecret);try {ossClient.putObject(bucketName, file.getOriginalFilename(), file.getInputStream());// 關(guān)閉OSSClient。ossClient.shutdown();return "https://" + bucketName + "." + endPoint + "/" + file.getOriginalFilename();} catch (Exception e) {e.printStackTrace();return null;}} }上述代碼會(huì)出現(xiàn)文件重名覆蓋的問(wèn)題,通過(guò)修改文件名解決文件重名覆蓋問(wèn)題,并按日期文件夾分類:
String fileName = file.getOriginalFilename(); //添加uuid防止文件重名 String uuid = UUID.randomUUID().toString().replaceAll("-", ""); fileName = uuid + fileName ; //添加日期,按日期創(chuàng)建文件夾對(duì)文件分類 String date = new DateTime().toString("yyyy/MM/dd"); fileName = date + "/" + fileName;三. nginx 請(qǐng)求轉(zhuǎn)發(fā)
1. nginx 基礎(chǔ)概念
由于現(xiàn)在后端有兩個(gè)服務(wù)(eduservice 和 oss),一個(gè)在 8081,一個(gè) 8082 端口,那前端發(fā)送的請(qǐng)求如何被正確轉(zhuǎn)發(fā)到對(duì)應(yīng)端口呢?答案是使用 **nginx **。
nginx 能夠?qū)崿F(xiàn):
2. 實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)
如何使用 nginx 實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)呢?
(1)首先下載 ngnix for windows,然后修改其配置文件 …\nginx-1.18.0\conf\nginx .conf:
http {server {listen 9001; //修改監(jiān)聽(tīng)的端口號(hào)防止沖突server_name localhost;//添加需要轉(zhuǎn)發(fā)的請(qǐng)求地址:~ 表示正則匹配location ~ /eduservice/ {proxy_pass http://localhost:8081;}location ~ /oss/ {proxy_pass http://localhost:8082;}} }(2)修改前端端口號(hào)為 nginx 中配置的端口號(hào):
(3)前端重新啟動(dòng),并啟動(dòng)后端兩個(gè)服務(wù)。再啟動(dòng) nginx 。注意啟動(dòng) nginx 前最好先 stop 掉它之前的進(jìn)程:
四. 頭像上傳前端代碼
1. 導(dǎo)入上傳文件模塊
確保 components 模塊下有這兩個(gè)模塊,沒(méi)有的話下載拷貝過(guò)來(lái)就行:
前端代碼導(dǎo)入模塊:
2. 頭像上傳組件
<el-form-item label="頭像"><!--頭像縮略圖--><pan-thumb :image="teacherForm.avatar"/><el-button type="primary" icon="el-icon-upload" @click="imageUploadShow=true">更換頭像</el-button>//點(diǎn)擊上傳文件后調(diào)用的組件<image-cropperv-show="imageUploadShow":width="300":height="300":key="imageKey" //用于重新初始化組件:url="BASE_API + '/oss/fileupload/avatar'" //后端文件上傳的url地址field="file"@close="close"@crop-upload-success="cropSuccess" //上傳成功后調(diào)用的方法/> </el-form-item> data() {return {imageUploadShow: false,BASE_API: process.env.BASE_API, //從dev.env.js文件中讀取的內(nèi)容imageKey: 0,} },添加方法的定義:
close() {this.imageUploadShow = falsethis.imageKey = this.imageKey + 1 //用于重新初始化組件,防止上次成功后第二次點(diǎn)擊上傳出現(xiàn)bug }, //這是上傳成功后調(diào)用的方法,自動(dòng)封裝data的內(nèi)容 cropSuccess(data) {this.imageUploadShow = falsethis.teacherForm.avatar = data.urlthis.imageKey = this.imageKey + 1 }五. EasyExcel的使用
后續(xù)內(nèi)容要用到 EasyExcel,這里先介紹下如何使用EasyExcel進(jìn)行讀寫。
1. 引入 pom 依賴
<dependencies><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.1</version></dependency> </dependencies>注意:其實(shí)還需要引入 poi 依賴,前面已經(jīng)引入過(guò)了。
2. 寫操作
建立一個(gè)實(shí)體類,用 @ExcelProperty 注解標(biāo)識(shí)它在 excel 表中的列名
@Data public class EasyExcelEntity {@ExcelProperty(value = "學(xué)生編號(hào)", index = 0)private Integer sno;@ExcelProperty(value = "學(xué)生姓名", index = 1)private String sname; }寫操作:
String fileName = "D:\\stu.xlsx"; List<EasyExcelEntity> stuList = new ArrayList<>(); for (int i = 0; i < 10; i++) {EasyExcelEntity entity = new EasyExcelEntity();entity.setSno(i);entity.setSname("hi" + i);stuList.add(entity); } EasyExcel.write(fileName, EasyExcelEntity.class).sheet("學(xué)生列表").doWrite(stuList);3. 讀操作
同樣需要上述一個(gè)實(shí)體類對(duì)應(yīng) excel 表中的列名,此外比 “寫操作” 更麻煩一點(diǎn)的是需要建立一個(gè)監(jiān)聽(tīng)器:
public class EasyExcelListener extends AnalysisEventListener<EasyExcelEntity> {//一行一行讀取代碼時(shí)進(jìn)行的操作@Overridepublic void invoke(EasyExcelEntity easyExcelEntity, AnalysisContext analysisContext) {System.out.println(easyExcelEntity.getSno() + ": " + easyExcelEntity.getSname());}//讀取完進(jìn)行的操作@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {} }讀操作:
EasyExcel.read(fileName, EasyExcelEntity.class, new EasyExcelListener()).sheet().doRead();總結(jié)
以上是生活随笔為你收集整理的Day6 - 头像存储与EasyExcel的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql 开启事物_mysql事务的开
- 下一篇: 详解 Python qrcode 二维码