项目截图
其中素材,以及一些关键代码的实现参考链接:一个云上相册
项目实现
简介
云图是一个基于springboot框架的个人云相册,能够实现简单的本地相片存储,最终用户存储的照片会存储于腾讯云存储桶。上传细节的实现请参照实现照片上传到腾讯云存储桶
本文博主重点描述一下在项目过程技术实现。
qq邮件功能
本项目实现了用qq邮件的形式实现账号的激活。
数据库部分用户表的设计:
STATUS代表账号激活情况,用户在注册成功后会受到一封qq邮件,点击qq邮件进行激活账号,STATUS中存储的信息也就由N->Y,代表账户激活成功(当然此处也可以用接收验证码实现,大体逻辑相同)。
一些实体类的实现博主在此便不再赘述,源码已放于文末
实现流程:
引入依赖
<!-- 文件上传使用的第三方库 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
MailUtils类
public final class MailUtils {
//20b30176d4526d69
private static final String USER = "2507062649@qq.com"; // 发件人称号,同邮箱地址
private static final String PASSWORD = ""; // 如果是qq邮箱可以使用授权码,或者登录密码,授权码获取方式下文已经给出
/**
* @param to 收件人邮箱
* @param text 邮件正文
* @param title 标题
*/
/* 发送验证信息的邮件 */
public static boolean sendMail(String to, String text, String title) {
try {
final Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "smtp.qq.com");
// 发件人的账号
props.put("mail.user", USER);
//发件人的密码
props.put("mail.password", PASSWORD);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
// 设置发件人
String username = props.getProperty("mail.user");
InternetAddress form = new InternetAddress(username);
message.setFrom(form);
// 设置收件人
InternetAddress toAddress = new InternetAddress(to);
message.setRecipient(Message.RecipientType.TO, toAddress);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(text, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws Exception { // 做测试用
MailUtils.sendMail("@qq.com", "阿狗在吗,晚上早点睡晚安。勿念勿回复。", "测试邮件");
System.out.println("发送成功");
}
}
图片上传部分代码实现
前端部分
home.html
<form id="fileForm" action="/image/upload" onsubmit="return checkFileSize()" method="post"
enctype="multipart/form-data" class="navbar-form navbar-left">
<div class="form-group" style="border-color: #3c3c3c">
<input id="files" class="form-control" type="file" name="upload" multiple required>
<input type="submit" class="btn btn-success" value="上传"/>
</div>
</form>
后端部分
@PostMapping("/upload")
public void upload(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//1.做准备工作,获得upload对象,该对象可以解析请求
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items;
try {
//1.1解析请求,获得文件项列表,关键代码实现
items = upload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
//解析请求对象失败
resp.sendRedirect("/user/error");
return;
}
//先遍历一遍文件项确保没有非图片类型的文件
for (FileItem item : items) {
if (!item.getContentType().contains("image")) {
//说明用户上传的不是图片,需要告诉用户
resp.sendRedirect("/user/error");
return;
}
}
//获取session中的登录信息
User user = (User) (req.getSession().getAttribute("user"));
//开始处理文件
for (FileItem item : items) {
//2.封装Image对象
Image image = new Image();
image.setUid(user.getId());
//2.1格式化上传时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
image.setUploadTime(format.format(new Date()));
//2.2获取文件的名字
image.setImageName(parseFileName(item.getName()));
image.setContentType(item.getContentType());
//2.3利用md5,用图片的二进制数据进行求MD5加密码,将来存储一样的图片时可以节省磁盘空间
image.setMd5(DigestUtils.md2Hex(item.get()));
//2.4设置路径,用MD5可以防止覆盖图片
//3.先写入磁盘(在写入前会查询数据库是否有数据,无则说明第一次存储图片,可以写入腾讯云存储桶)
//3.1获取项目的部署路径
/*File file = new File(image.getPath());*/
try {
//再写入磁盘之前我们先查询一下数据库中是否有了该图片
Image imageByMD5 = imageService.findImageByMD5(image.getMd5(), user.getId());
if (imageByMD5 == null) {
//数据库中没有该图片,说明是第一次存储,这时候我们才写入云存储桶
/* item.write(file);*/此处实现的是一个写入本地磁盘的接口,可以根据需要自行选择
//将FIleItem对象转为File对象
File toFile = new File(image.getImageName());
item.write(toFile);
//上传到腾讯云存储桶
String fileName = TencentCOS.uploadfile(toFile);//参见上文简介中链接
image.setPath(fileName);//此处的fileName即为云存储桶中的路径了
image.setSize((int) item.getSize());
}
//4.不管磁盘写不写入,数据库中的记录都要写进去
imageService.insertImage(image);
} catch (Exception e) {
e.printStackTrace();
//写入磁盘出错
resp.sendRedirect("/user/error");
return;
}
}
//因为是多文件,所以当所有文件都处理完毕后再重定向
//这里我们可以重定向刷新页面
resp.sendRedirect(req.getContextPath() + "/user/home");
}
其中代码中一些MD5加密作者在此就不再赘述
关于代码中的TencentCOS.upload()函数就是实现就在博主在简介链接中。
图片显示部分代码实现
前端部分
<div v-for="image in images" style="border-radius: 15%">
<img id="sImage" style="border-radius: 10%;width: 200px;height: 200px;"
v-bind:src="'/image/show?imageId='+image.imageId" v-on:click="showBigImage(image.imageId)"
alt="图片正在拼命加载">
<font style="font-family: SimSun;font-size: 12px">{{image.imageName}}</font><br/>
<font style="font-family: SimSun;font-size: 12px">上传时间:{{image.uploadTime}}</font><br/>
<button style="border-radius: 100%;background-color: aquamarine;float: left"
v-on:click.stop="deleteImage(image.imageId)">弃
</button>
<button style="border-radius: 100%;background-color: aquamarine;float: right;" v-on:click.stop="downloadImage(image.imageId)">摘</button>
</div>
后端部分
@GetMapping("/show")
public void show(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ResultInfo info = new ResultInfo();
//先获取当前的用户id
User user = (User) (req.getSession().getAttribute("user"));
//1.获取请求参数的imageId,根据该参数查询图片
String imageId = req.getParameter("imageId");
if (imageId == null || "".equals(imageId)) {
//没有改imageId的值就无法访问
info.setFlag(false);
info.setErrorMsg("因神秘力量干扰,无法访问");
writeValue(info, resp);
return;
}
Image image = imageService.findByImageId(Integer.parseInt(imageId), user.getId());
//输出字节流到浏览器
//File file = new File(image.getPath());
byte[] buffer = new byte[1024 * 20];
//1.创建输入流,用于写入缓冲区
/* BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));*///从本地文件中获取输入流写到缓存区
BufferedInputStream in = new BufferedInputStream(TencentCOS.showFile(image.getPath()));
//2.创建输出流,用于输出数据
//2.1这里记得设置类型,否则会显示失败
resp.setContentType(image.getContentType());
BufferedOutputStream out = new BufferedOutputStream(resp.getOutputStream());
while (true) {
int len = in.read(buffer);
if (len == -1) {
//数据读取完毕
break;
} else {
out.write(buffer);//将字节流写到网页中,img标签便会显示图片
}
}
//记得关闭
in.close();
out.close();
}
至于删除图片以及下载图片到本地的功能博主在这里就不再详述了,有兴趣的小伙伴可以下载本程序的源码,由于博主也是参考别人的代码实现,所以小伙伴们引用时请注明出处。(文末附源码下载地址)