怎么保证用富文本编辑器不让服务器产生垃圾图片,神器redis的发布订阅

探讨富文本编辑器中两种图片上传方式:直接上传至服务器与base64编码上传,分析各自的优缺点及服务器垃圾图片问题解决方案,包括通过Redis处理未提交文章中的临时图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先描述一下个人经历吧,用过的富文本编辑器也有几个,图片处理这块,总结一下,我遇到的有两种,一种是选择了图片,富文本显示的是图片文件的src的属性是base64编码,一种是,选择了图片之后直接上传到服务器,这时,富文本显示的是图片文件的src属性是服务器的地址。

刚开始做项目的时候用的是百度editor,当时觉得复杂,觉得能实现图片上传就是成功,他的方式就是第二种,当你选择了图片,图片直接被上传到服务器,但这种方式有个不好的地方,就是当你上传一张图片成功后,按了一下退格,那会怎么样,浏览器不显示图片了,但服务器上还有。但用户不知情,会导致服务器垃圾文件越来越多,当用户重新编辑文章的时候,删除图片,也不会删除服务器的图片(当然,开发者最清楚这件事了!),一会说解决办法。

后来,我接触了base64编码的方式,就是第一种。我是这样想的,用户选择一张图片,是js处理之后,将图片的src路径改为了大长串的base64码,(在用户眼里,图片也是正常显示),但不会上传到后台服务器,这貌似很又好了,对服务器来说。当用户点击提交的时候,富文本中包含大量的base64码的图片,(刚开始想直接放进数据库,但考虑到数据库可能导致存储空间紧张),服务器用正则表达式解析富文本提交过来的文章内容,然后编码成图片文件,然后将文章内容中图片的src改成服务器地址,这样能省数据库空间。但是,当用户编辑文章的时候就麻烦了,用户编辑文章,图片显示的还是服务器地址,用户在富文本内,删除图片,服务器还是没有删除,当用户重新选择图片,又是base64码,当点击提交的时候,服务器解析图片文件的src的时候要分开处理,如果是base64的,就转成文件,如果不是则不作处理。但还是没解决用户重新编辑文章删除图片的问题,一会说解决办法。(后来才发现,这样上传方式凸显了我的天真和青涩)。

先处理第一种和第二种上传文章的编辑的时候服务器的删除问题吧,(解决思路是,找到用户在编辑的时候删除的图片,也让服务器删除),当我点击编辑文章的时候,我会把回显回来的内容进行js解析,这两种图片的回显都是服务器地址哦!js怎么解析呢,正则表达式匹配所有图片,生成一个数组,旧图片数组,当用户编辑完成图片的时候也渠道富文本的内容,也生成一个数组,新图片数组。旧图片数组全是,服务器地址的图片路径,新图片数组,只收集全是服务器地址的图片路径,用户新上传的图片是base64的,需要服务器保存的。这样两个数组进行对比,可以找出用户在富文本中删除了那几张图片。把这个需要删除的图片数组传给后台,后台删除图片即可。这样确实解决的编辑的时候的图片删除问题。

base64上传还产生了新问题(我发现,使用base64上传图片,这个base64码即使使用canvas做一下压缩,20来张图片的话,富文本内容长度就会数十万,根本无法提交到后台,真以为post请求可以无限长度呢),于是base64这个方案破灭了,又重写了base64上传的方法,把图片扔到服务器,在回显服务的路径。又和第一种方案一样了。

用户的编辑文章解决了服务器的垃圾图片问题。正准备开心的时候,突然想到,如果用户添加文章的时候,选择了几张图片,这时图片已经到了服务器上,但用户重新刷新了页面怎么办,或者说用户不想写文章,睡觉去了怎么办。

新问题就有新方案!

解决思路,用户每上传一张图片,就把图片存放的路径扔redis里面,设置超时时间,比如预设,用户在8小时之内一定会将编写的文章提交了,所以redis设置key就是图片路径,value随意。redis有发布订阅机制,可以在key超时时,将过期的key返回推送给java程序,这样处理就很好了。如果用户选择了图片,上传到服务器了,没有点击提交,过期了之后程序还是会删除服务器上的图片,如果上传了,那就用程序删除redis里的key,那样不会触发key的超时推送。这就就解决了用户上传一堆图,但是没有提交文章的问题。

具体配置如下:

修改redis.conf设置key超时提醒

 在大概1024行这样设置,版本不同可能位置不同。

在springboot设置redis订阅的配置文件:

@Bean //相当于xml中的bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //订阅了一个叫具体的 的通道
        container.addMessageListener(listenerAdapter, new PatternTopic("__key*@0__:expired"));
        //这个container 可以添加多个 messageListener
        return container;
    }

    /**
     * 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法
     * @param receiver
     * @return
     */
    @Bean
    MessageListenerAdapter listenerAdapter(ReceiverService receiver) {
        /*这个地方 是给messageListenerAdapter 传入一个消息接受的处理器,利用反射的方法调用“receiveMessage”
        也有好几个重载方法,这边默认调用处理器的方法 叫handleMessage 可以自己到源码里面看

        这里实质就是监听调用ReceiverService类中的receiveMessage方法
        */
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

这是处理信息的类:

package com.xinxiera.config;

import java.io.File;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ReceiverService {
	@Value("${windows.path}")
	private String windowsPath;
	@Value("${linux.path}")
	private String linuxPath;
	public void receiveMessage(String key) {
		//订阅了redis的Key超时,会返回redis删除的key,服务器需要删除图片
        if(key.startsWith("uploadedImg")) {
        	String path = null;
        	String os = System.getProperty("os.name");
    		if(os.toLowerCase().startsWith("win")){
    			path = windowsPath;
    		}else {
    			path = linuxPath;
    		}
    		File file = new File(path+key.substring(12));
    		if(file.exists()) {
    			file.delete();
    		}
        }
    }
}

这样即使用户上传了图片,关了浏览器,图片也会被服务器删除;

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值