目录
阳光沙滩博客系统-管理中心图片模块

图片的上传管理有多种方案,可以使用服务商提供的对象存储,只要是文件都可以。按存储空间和流量计费,也有一些其他的服务,例如转码之类的。

也可以用fastDFS, 这个也用得比较多,以前。搭建起来比较麻烦,这里不详细说,有兴趣的同学可以自行尝试。

这里我们只是普通的文件上传,没有做太多的优化处理。同学们跟着来做就好,先完成功能先吧。

图片上传

接口

java
复制代码
/**
     * 关于图片(文件)上传
     * 一般来说,现在比较常用的是对象存储--->很简单,看文档就可以学会了
     * 使用 Nginx + fastDFS == > fastDFS -- > 处理文件上传, Nginx -- > 负责处理文件访问
     *
     * @param file
     * @return
     */
@PreAuthorize("@permission.admin()")
@PostMapping
public ResponseResult uploadImage(@RequestParam("file") MultipartFile file) {
    return imageService.uploadImage(file);
}

上传图片实现

java
复制代码

    /**
     * 上传的路径:可以配置,在配置文件里配置
     * 上传的内容,命名-->可以用ID,-->每天一个文件夹保存
     * 限制文件大小,通过配置文件配置
     * 保存记录到数据库里
     * ID|存储路径|url|原名称|用户ID|状态|创建日期|更新日期
     *
     * @param file
     * @return
     */
    @Override
    public ResponseResult uploadImage(MultipartFile file) {
        //判断是否有文件
        if (file == null) {
            return ResponseResult.FAILED("图片不可以为空.");
        }
        //判断文件类型,我们只支持图片上传,比如说:png,jpg,gif
        String contentType = file.getContentType();
        log.info("contentType == > " + contentType);
        if (TextUtils.isEmpty(contentType)) {
            return ResponseResult.FAILED("图片格式错误.");
        }
        //获取相关数据,比如说文件类型,文件名称
        String originalFilename = file.getOriginalFilename();
        log.info("originalFilename == > " + originalFilename);
        String type = getType(contentType, originalFilename);
        if (type == null) {
            return ResponseResult.FAILED("不支持此图片类型");
        }
        //限制文件的大小
        long size = file.getSize();
        log.info("maxSize === > " + maxSize + "  size ==> " + size);
        if (size > maxSize) {
            return ResponseResult.FAILED("图片最大仅支持" + (maxSize / 1024 / 1024) + "Mb");
        }
        //创建图片的保存目录
        //规则:配置目录/日期/类型/ID.类型
        long currentMillions = System.currentTimeMillis();
        String currentDay = simpleDateFormat.format(currentMillions);
        log.info("current day == > " + currentDay);
        String dayPath = imagePath + File.separator + currentDay;
        File dayPathFile = new File(dayPath);
        //判断日期文件夹是否存在//2020_06_26
        if (!dayPathFile.exists()) {
            dayPathFile.mkdirs();
        }
        String targetName = String.valueOf(idWorker.nextId());
        String targetPath = dayPath +
                File.separator + type + File.separator + targetName + "." + type;
        File targetFile = new File(targetPath);
        //判断类型文件夹是否存在//gif
        if (!targetFile.getParentFile().exists()) {
            targetFile.getParentFile().mkdirs();
        }
        try {
            if (!targetFile.exists()) {
                targetFile.createNewFile();
            }
            log.info("targetFile == > " + targetFile);
            //保存文件
            file.transferTo(targetFile);
            //返回结果:包含这个图片的名称和访问路径
            //第一个是访问路径 -- > 得对应着解析来
            Map<String, String> result = new HashMap<>();
            String resultPath = currentMillions + "_" + targetName + "." + type;
            result.put("id", resultPath);
            //第二个是名称--->alt="图片描述",如果不写,前端可以使用名称作为这个描述
            result.put("name", originalFilename);
            Image image = new Image();
            image.setContentType(contentType);
            image.setId(targetName);
            image.setCreateTime(new Date());
            image.setUpdateTime(new Date());
            image.setPath(targetFile.getPath());
            image.setName(originalFilename);
            image.setUrl(resultPath);
            image.setState("1");
            SobUser sobUser = userService.checkSobUser();
            image.setUserId(sobUser.getId());
            //记录文件
            //保存记录到数据里
            imageDao.save(image);
            //返回结果
            return ResponseResult.SUCCESS("文件上传成功").setData(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseResult.FAILED("图片上传失败,请稍后重试");
    }

两个配置项

yml
复制代码
@Value("${sob.blog.image.save-path}")
public String imagePath;

@Value("${sob.blog.image.max-size}")
public long maxSize;
java
复制代码
sob.blog.image.save-path: E:\codes\Idear\images
# 2MB
sob.blog.image.max-size: 2097152

获取图片列表

使用场景:发表文章的时候,获取到图片列表,然后插入图片

接口

java
复制代码
@PreAuthorize("@permission.admin()")
@GetMapping("/list/{page}/{size}")
public ResponseResult listImages(@PathVariable("page") int page, @PathVariable("size") int size){
    return imageService.listImages(page, size);
}

获取图片列表实现

java
复制代码
@Override
    public ResponseResult listImages(int page, int size) {
        //处理page,size
        page = checkPage(page);
        size = checkPage(size);
        SobUser sobUser = userService.checkSobUser();
        if (sobUser == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        //创建分页条件
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        //查询
        Pageable pageable = PageRequest.of(page - 1, size, sort);
        //返回结果
        final String userId = sobUser.getId();
        Page<Image> all = imageDao.findAll(new Specification<Image>() {
            @Override
            public Predicate toPredicate(Root<Image> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                //根据用户ID
                Predicate userIdPre = cb.equal(root.get("userId").as(String.class), userId);
                //根据状态
                Predicate statePre = cb.equal(root.get("state").as(String.class), "1");
                return cb.and(userIdPre, statePre);
            }
        }, pageable);
        return ResponseResult.SUCCESS("获取图片列表成功.").setData(all);
    }

图片删除

删除图片我们不是真的删除,只是修改其状态,如果真的删除了,则会访问不了了。有些图片,可能被多个文章引用着,如果删除一张图片去检查文章是否有引用,这个资源消耗比较多,当然啦,也可以用统计法。如果图片有被引用则记录一下值,得加多一张表记录一下。

这里我们只是修改图片的状态

需要管理员权限

java
复制代码
@PreAuthorize("@permission.admin()")
@DeleteMapping("/{imageId}")
public ResponseResult deleteImage(@PathVariable("imageId") String imageId) {
    return imageService.deleteById(imageId);
}

实现代码

java
复制代码
/**
     * 删除图片,
     * 只改变状态
     *
     * @param imageId
     * @return
     */
@Override
public ResponseResult deleteById(String imageId) {
    int result = imageDao.deleteImageByUpdateState(imageId);
    if (result > 0) {
        return ResponseResult.SUCCESS("删除成功.");
    }
    return ResponseResult.FAILED("图片不存在.");
}

DAO修改语句

java
复制代码
@Modifying
@Query(nativeQuery = true, value = "UPDATE `tb_images` SET `state` = '0' WHERE id = ?")
int deleteImageByUpdateState(String imageId);
本文由 拉大锯 原创发布于 阳光沙滩 , 未经作者授权,禁止转载
评论
0 / 1024
推荐文章
Linux 防火墙完全指南:从原理到多发行版实战
本文全面解析Linux防火墙的底层原理与主流工具配置,涵盖UFW、firewalld、iptables、nftables等方案,适合不同发行版用户。从基础概念到生产环境加固建议,助你掌握核心安全策略,确保服务器与网络的安全运行。
水上派对英语单词篇
探索FLOATOPIA水上派对的完整指南,涵盖签到流程、场地指引、安全须知、活动安排及夜场舞会等实用英语词汇与对话。无论是初学者还是老手,都能轻松掌握关键术语,享受完美水上体验。
麒麟操作系统下使用 virt-customize 重置虚拟机 root 密码实战
本文详细介绍了在麒麟操作系统环境下使用 virt-customize 工具重置 KVM 虚拟机 root 密码的完整流程,包含安装步骤、常见问题及解决方案,帮助运维人员高效处理密码遗忘或批量初始化场景,避免数据丢失。
浅析JS预编译-函数篇
本文详细讲解了JavaScript中函数的预编译过程,包括AO对象的创建、变量和函数声明的提升,以及执行阶段的变化。适合初学者了解JS执行机制,帮助深入理解代码运行逻辑。
访问Github的另一种姿势
本文介绍了如何通过Watt ToolKit等工具加速访问Github,适合对网络技术感兴趣的读者。内容涵盖工具介绍、下载和使用方法,以及一些实用技巧,值得一看。
使用Gulp压缩JS
本文详细介绍了如何使用Gulp压缩JavaScript文件,特别是支持ES6语法的处理方法。通过实际操作和效果对比,帮助开发者提升代码性能,适合对前端自动化工具感兴趣的读者。
使用Gulp压缩CSS
本文详细介绍了如何使用Gulp工具对CSS文件进行压缩,提升网页加载速度。适合需要优化静态资源的开发者,提供清晰的步骤和示例,帮助快速上手。
从0部署Nuxtjs项目
本文详细介绍了如何将Nuxt.js项目部署到公网,涵盖Node.js安装、环境配置、源码上传及使用PM2启动服务的全过程,适合开发者学习和实践。
Linux 命令行美化利器:tree 命令完全指南(安装 + 全部参数详解)
掌握 Linux 下的 `tree` 命令,快速直观地查看目录结构。本文详细讲解安装方法、参数含义及实战场景,适合开发者和系统管理员提升工作效率。
Linux常用命令(一)
本文详细介绍了Linux基础命令,包括文件操作、系统显示、网络状态、软件包管理等,适合初学者学习和查阅,是掌握Linux系统的实用指南。
大模型推理参数解码:温度、Top-p 与核采样如何塑造生成文本的灵魂
探索大语言模型的采样参数如何塑造生成内容,从温度到Top-p,从惩罚机制到熵控制,揭示背后的信息论原理与实践策略。了解如何通过参数调优,让AI既保持知识的严谨,又拥有创造力的自由。
记从0使用Claude code写代码
本文介绍了如何使用Claude Code搭配DeepSeek进行编程,详细讲解了安装Node.js、全局安装Claude、配置模型以及使用方法。对于开发者来说,这是一份实用的技术教程,尤其适合对AI编程工具感兴趣的读者。
Android-Studio-Gradle同步失败-Library为null的通用排查指南
遇到 Android Studio Gradle Sync 失败时,不要轻易删除全局缓存。本文详细解析了错误原因,并提供了一系列精准的排查步骤和解决方案,帮助开发者快速定位并解决问题,提升开发效率。
PHP实现密码加密
本文详细介绍了Bcrypt密码加密技术及其在PHP中的应用,帮助开发者提升用户密码的安全性。通过实际代码示例,展示了如何使用password_hash和password_verify函数进行密码加密与验证,是学习网络安全知识的实用指南。
WordCloud效果,滚动标签
本文详细介绍了如何在Vue项目中集成WordCloud组件,包括依赖安装、属性配置和使用方法。适合开发者学习如何实现数据可视化功能,提升项目交互体验。
从0使用WordPress搭建一个优美的网站
本文详细介绍了如何使用WordPress搭建一个美观的网站,从安装到主题配置和功能拓展,为读者提供了实用的操作指南。无论是初学者还是有一定经验的开发者,都能从中获得有价值的参考。
JS实现在网站底部添加运行时间
想知道如何在网站底部显示运行时间?本文详细讲解了通过JavaScript实现这一功能的方法,包括时间计算逻辑和代码实现。适合前端开发者学习参考,轻松为网站添加实用功能。
在Vercel上部署Hexo博客
本文详细介绍了如何在Vercel上快速部署Hexo博客,无需后端服务即可实现高效发布。相比传统方式,省去了手动生成和上传静态文件的步骤,更加便捷。适合想要搭建个人博客的开发者参考。
从0搭建一个Hexo博客
本文详细介绍了Hexo博客框架的使用方法,从安装到部署全流程讲解,适合想快速搭建个人博客的技术爱好者。内容清晰易懂,是入门Hexo的理想指南。
离线设备激活方案:古老的 Windows 光盘激活,离线算法授权等
本文深入解析了离线激活的核心原理与实现方式,从历史案例到现代技术,全面剖析了如何在无网络环境下确保软件授权的安全性。通过设备指纹、授权文件校验等手段,为开发者提供了可复用的架构设计思路,适用于工业、医疗等对网络依赖较低的场景。
Hexo实现生成站点地图
想为你的Hexo博客添加站点地图功能吗?本文详细介绍了如何通过安装插件和配置文件来实现,适合没有内置该功能的新主题或自定义主题的用户。简单步骤助你提升搜索引擎优化效果。
Hexo实现代码压缩
本文分享了如何通过Hexo插件优化博客性能,详细介绍了安装和配置过程,帮助提升网页加载速度。适合对网站优化感兴趣的开发者阅读。
记一次 GitHub 幽灵协作者大清洗:强制重写 Git 历史与穿透 CDN 缓存实践
本文详细讲解了如何解决GitHub上出现的‘幽灵协作者’问题,通过重写Git历史和穿透CDN缓存,彻底清理错误提交记录。适合开发者学习如何高效管理项目历史与优化仓库信息。
从一行 `native` 堆栈追到 InstallReferrer:一次主线程 ANR 的排查全过程
本文详细记录了一次主线程ANR的排查过程,从一行native堆栈追踪到InstallReferrer服务调用。通过分析堆栈、源码和系统调用,揭示了归因SDK在主线程同步调用Play商店服务导致的ANR问题,并提供了多维度的解决方案。对于Android开发者来说,是一篇深入浅出的技术实践指南。
Linux从 HelloWorld 到数据库服务注册
本文详细解析了Linux系统中服务注册的概念与实现,通过一个简单的Hello World示例,帮助读者理解如何将程序注册为systemd服务,并掌握相关操作命令。无论是数据库还是其他应用,了解服务注册机制都是系统管理的重要基础。
学习虚拟机的笔记
linux ps 命令详解,跟着敲一次就掌握了
深入了解 Linux 中最常用的进程查看命令 `ps`,掌握其各种用法和参数,适用于系统管理和故障排查。从基础到高级,全面解析 `ps` 的使用技巧,帮助您提升 Linux 运维技能。
ObjectMapper 入门:Java 对象与 JSON 之间的「翻译官」
了解ObjectMapper在Java中如何实现对象与JSON的转换,掌握其在Spring Boot项目中的应用及常见使用场景。本文详细解析了序列化/反序列化过程、API用法、与Spring MVC的关系以及与其他JSON库的对比,适合开发者快速上手和深入理解。
服务器一次中病毒的记录
本文详细描述了一次服务器异常流量的排查过程,发现大量外部IP与内部服务建立连接,疑似存在恶意程序。通过分析日志和图片,确认为恶意程序导致带宽占用过高,最终通过备份和删除操作解决问题。文章提供了技术排查思路和解决方案,对系统维护具有参考价值。
JavaWeb微服务脚手架搭建
本文介绍了构建微服务架构时常用的开发模板和核心组件,涵盖技术选型、依赖配置及版本差异分析。通过合理选择 Java 和 Spring Boot 版本,可以显著提升开发效率和系统性能,是开发者不可错过的实践指南。