首页 > 其他分享 >SpringBoot 打造图片阅后即焚功能

SpringBoot 打造图片阅后即焚功能

时间:2024-11-13 11:41:17浏览次数:1  
标签:阅后 SpringBoot image springframework org import 打造 上传 public

本系统主要使用以下技术栈:

  1. 后端:Spring Boot —— 采用此框架可以快速构建和部署RESTful API,并具备良好的可扩展性。
  2. 数据库:MySQL —— 作为关系型数据库,MySQL具有强大的数据管理能力,适合存储和查询结构化数据。
  3. 前端:Thymeleaf + HTML/CSS/JavaScript —— Thymeleaf作为模板引擎,可以快速生成动态HTML页面。
  4. 文件存储:本地文件系统或云存储服务(如 AWS S3)—— 提供灵活的文件存储方案。

以下是系统架构图,展示了各个模块之间的关系:

创建Spring Boot项目:

使用Spring Initializr(start.spring.io/)创建一个新的Spring Boot项目,选择以下依赖:
- Spring Web:用于构建RESTful API。
- Spring Data JPA:简化数据访问层的开发。
- MySQL Driver:用于连接MySQL数据库。
- Thymeleaf:用于生成动态网页。

在生成项目后,将其导入到IDE中(如IntelliJ IDEA或Eclipse),并确保项目可以正常编译和运行。

数据库配置:

在MySQL中创建一个新的数据库,例如 image_sharing_db。可以使用以下SQL命令:

点击查看代码
CREATE DATABASE image_sharing_db;

然后在 application.properties 文件中配置数据库连接:

点击查看代码
# MySQL 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/image_sharing_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

添加依赖

确保在 pom.xml 中添加以下依赖:

点击查看代码
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

文件存储目录

为了存储用户上传的图片,需要在项目中创建一个文件存储目录。可以在项目根目录下创建一个名为 uploads 的文件夹,确保该文件夹具有可写权限。 数据模型设计
创建一个 Image 实体类,表示上传的图片信息。包括文件名、上传时间、过期时间等字段。

点击查看代码
import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
public class Image {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // 图片ID
    private String filename; // 文件名
    private LocalDateTime uploadTime; // 上传时间
    private LocalDateTime expirationTime; // 过期时间

    // getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public LocalDateTime getUploadTime() {
        return uploadTime;
    }

    public void setUploadTime(LocalDateTime uploadTime) {
        this.uploadTime = uploadTime;
    }

    public LocalDateTime getExpirationTime() {
        return expirationTime;
    }

    public void setExpirationTime(LocalDateTime expirationTime) {
        this.expirationTime = expirationTime;
    }
}

数据访问层

创建一个数据访问接口 ImageRepository,用于与数据库交互。

点击查看代码
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ImageRepository extends JpaRepository<Image, Long> {
}

这里我们使用 JpaRepository 提供的基本CRUD操作,方便对 Image 实体的数据库操作。 控制器实现
创建一个控制器 ImageController,处理图片的上传和查看请求。

点击查看代码
package com.example.demo.controller;

import com.example.demo.entity.Image;
import com.example.demo.repository.ImageRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;

/**
 * By zhangT
 */
@Controller
@RequestMapping("/images")
public class ImageController {

    private static final String UPLOAD_DIR = "src/main/resources/static/uploads/";
    @Autowired
    private ImageRepository imageRepository;

    @GetMapping("/upload")
    public String uploadPage() {
        return "upload"; // 返回上传页面视图
    }

    @PostMapping("/upload")
    public String uploadImage(@RequestParam("file") MultipartFile file, Model model) {

        String filename = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
        Path path = Paths.get(UPLOAD_DIR + filename);

        try {
            Files.createDirectories(path.getParent());
            file.transferTo(path);

            // 保存文件信息到数据库
            Image image = new Image();
            image.setFilename(filename);
            image.setUploadTime(LocalDateTime.now());
            image.setExpirationTime(LocalDateTime.now().plusMinutes(1)); // 设置过期时间为1分钟
            Image savedImage = imageRepository.save(image);

            // 添加图片链接和ID到页面模型
            model.addAttribute("message", "Image_Uploaded_Successfully.");
            model.addAttribute("imageUrl", "/uploads/" + filename);
            model.addAttribute("imageId", savedImage.getId());
        } catch (IOException e) {
            model.addAttribute("message", "Failed to upload image: " + e.getMessage());
        }

        return "upload"; // 返回上传页面视图
    }
    @PostMapping("/burn/{id}")
    public ResponseEntity<String> burnImage(@PathVariable Long id) {
        Optional<Image> imageOptional = imageRepository.findById(id);
        if (imageOptional.isPresent()) {
            Image image = imageOptional.get();
            Path path = Paths.get("src/main/resources/static/uploads/" + image.getFilename());
            try {
                Files.deleteIfExists(path);
                imageRepository.delete(image);
                return ResponseEntity.ok("Image burned successfully");
            } catch (IOException e) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to burn image");
            }
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Image not found");
    }
}

用户界面设计

创建 upload.html,让用户可以上传图片,显示用户上传的图片,提示用户图片已过期。

点击查看代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阅后即焚</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        .upload-container {
            margin-top: 50px;
            text-align: center;
        }
        .preview-container img {
            max-width: 100%;
            height: auto;
            margin-top: 10px;
        }
        .message {
            color: green;
            font-weight: bold;
            margin-top: 10px;
        }
         /* 燃烧效果的 CSS */
        .burn {
            animation: burn 1s forwards;
        }

        @keyframes burn {
            from {
                opacity: 1;
            }
            to {
                opacity: 0;
                transform: scale(1.5);
            }
        }

        #imageContainer {
            position: relative;
        }

        #burnEffect {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(255, 0, 0, 0.5);
            display: none;
            z-index: 10;
        }
    </style>
</head>
<body>
<div class="upload-container">
    <h1>阅后即焚</h1>
    <form action="/images/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" required>
        <button type="submit">Upload</button>
    </form>
    <p th:text="${message}" class="message"></p>
</div>

<div d="imageContainer" class="preview-container" th:if="${imageUrl}">
    <h2>图片预览</h2>
    <img th:src="${imageUrl}" alt="上传图片">
    <div id="burnEffect"></div>
</div>

<button id="burnButton">阅后即焚</button>

<script>
    // 点击阅后即焚按钮的事件
    document.getElementById("burnButton").onclick = function() {
        const burnEffect = document.getElementById("burnEffect");
        burnEffect.style.display = "block";  // 显示燃烧效果
        burnEffect.classList.add("burn");    // 添加燃烧动画效果

        // 延迟后删除图片
        setTimeout(function() {
            document.querySelector("img").style.display = "none"; // 隐藏图片
            burnEffect.style.display = "none";  // 隐藏燃烧效果
            alert("图片已阅后即焚,无法恢复。");
        }, 2000); // 1秒后删除
    };

    // 向服务器发送阅后即焚请求
<!--    const imageId = /*[[${imageId}]]*/ 0;-->
<!--    fetch(`/burn/${imageId}`, { method: 'POST' })-->
<!--        .then(response => {-->
<!--            if (response.ok) {-->
<!--                response.text().then(msg => {-->
<!--                    console.log(msg);-->
<!--                    setTimeout(() => {-->
<!--                        imageElement.style.display = 'none';-->
<!--                        burnButton.style.display = 'none';-->
<!--                    }, 2000);  // 燃烧效果结束后隐藏图片-->
<!--                });-->
<!--            } else {-->
<!--                console.error("Failed to burn image.");-->
<!--            }-->
<!--        });-->
</script>
</body>
</html>

错误处理

在 ImageController 中实现统一的错误处理机制,捕获并处理可能出现的异常。可以通过 @ControllerAdvice 来实现全局异常处理:

点击查看代码
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleRuntimeException(RuntimeException e, Model model) {
        model.addAttribute("message", "An error occurred: " + e.getMessage());
        return "error"; // 返回错误页面视图
    }
}

系统优化

为了提高系统性能,可以考虑以下优化策略:
图片压缩:在上传图片时,压缩图片以减少存储空间和上传时间。可以使用第三方库如 Thumbnailator 进行图片处理。
异步处理:将图片的处理和存储任务异步化,避免阻塞用户请求。可以使用 @Async 注解或消息队列实现。
安全性
文件名安全性:为了避免文件名冲突和安全隐患,上传的文件名可以使用UUID进行重命名。

点击查看代码
import java.util.UUID;

// 在uploadImage方法中生成新的文件名
String newFilename = UUID.randomUUID().toString() + "_" + filename;
Path path = Paths.get(UPLOAD_DIR + newFilename);
文件类型检查:确保上传的文件是图片格式(如JPEG、PNG等),避免用户上传恶意文件。
点击查看代码
String contentType = file.getContentType();
if (!contentType.startsWith("image/")) {
    model.addAttribute("message", "Please upload a valid image file.");
    return "upload";
}

日志记录

使用 SLF4J 和 Logback 记录系统运行日志,包括上传、查看和错误信息,以便后期分析和监控。

点击查看代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ImageController {
    private static final Logger logger = LoggerFactory.getLogger(ImageController.class);

    // 在相应的位置记录日志
    logger.info("Image uploaded successfully: {}", filename);
}

部署

可以使用Docker容器化部署Spring Boot应用,确保其在各个环境中都能稳定运行。编写 Dockerfile,配置相应的基础镜像和运行环境。
点击查看代码
FROM openjdk:11-jre-slim
VOLUME /tmp
COPY target/image-sharing-app.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

来源:juejin.cn/post/7433068127786909731

标签:阅后,SpringBoot,image,springframework,org,import,打造,上传,public
From: https://www.cnblogs.com/ls-syh/p/18543590

相关文章

  • [免费]SpringBoot+Vue3校园宿舍管理系统(优质版)【论文+源码+SQL脚本】
    大家好,我是java1234_小锋老师,看到一个不错的SpringBoot+Vue3校园宿舍管理系统(优质版),分享下哈。项目视频演示【免费】SpringBoot+Vue3校园宿舍管理系统(优质版)Java毕业设计_哔哩哔哩_bilibili项目介绍随着信息技术的不断发展,现代化的校园管理需求日益增多,尤其在校园宿......
  • SpringBoot基础入门篇
    SpringBoot就是来快速构建spring项目的一门技术,而spring是javaE开发必不可少的框架。也是现在目前的企业中也被广泛应用。概述SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代......
  • SpringBoot校园社团活动管理系统t8w5k 程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:社员,社长,社团介绍,社员社团,社团类别,社团新闻,活动申请,社员活动申请开题报告内容一、选题背景与意义随着高校教育的快速发展,社团活动已成为培养学......
  • SpringBoot校园社交平台2t366 程序+源码+数据库+调试部署+开发环境
    题目:SpringBoot校园社交平台2t366进度安排:(1)2024年11月1日-2024年11月15日 确定选题,下达任务书,撰写开题报告;(2)2024年11月15日-2024年12月20日提交开题报告定稿;(3)2024年12月21日-2025年3月14日 完成选题的设计、论文大纲的撰写;(4)2025年3月15日-2025年3月21日  毕业(设......
  • 干货!TEMU爆款选品打造的一些攻略
    选品对于做Temu来说,是尤为重要的,接下来这篇选品攻略对于做TEMU的你有很大帮助。原文链接:干货!TEMU爆款选品打造的一些攻略选品重点方向质量杜绝低廉、低品质商品。产品质量的好坏事关店铺的评分,直接影响权重。重量尺寸优先1kg以内商品最好,尤其是500g以内,1kg以上商品,除非......
  • SpringBoot 处理 CORS 跨域请求的三种方法
    原文链接:SpringBoot处理CORS跨域请求的三种方法–每天进步一点点 0.前言pringboot跨域问题,是当前主流web开发人员都绕不开的难题。但我们首先要明确以下几点跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/java等其它环境跨域请求能发出去,服务端能收到请求并......
  • 【springboot应用】Spring Boot 3.3 + Neo4j:轻松实现图数据库操作的完全指南
    简介:Neo4j和SpringBoot集成Neo4j是一种开源的NoSQL图数据库,专为处理关联性强的大数据而设计。传统的关系型数据库(RDBMS)不擅长处理大量的关系数据,而Neo4j则通过基于图的模型使这些关系处理得更高效、直观。SpringBoot提供了很多与Neo4j集成的便捷工具,如spring-boot-......
  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现五
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现六
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • 芒果YOLO11改进90:检测头篇之ShareSepHead:即插即用|原创新颖共享Sep检测头,更省参数量,更
    ......