onlineSchool 项目课 四 :对项目图片的处理

一,实现图片的预览。
1, 标签预留图片上传的位置。

<img id="imagePreview" style="width: 220px;height: 90px;background-size: contain;background-image: url('/file/attachment/${(entity.picture)!}/0');">                   

2,选择的input,可以选择图片文件。

 <input id="file" type="file" style="margin-top: 3px">

3,设置隐藏的input 可以把图片数据提交到后台。

 <input id="recommendPicture" type="hidden">

4,jquery 的 change事件判断有没有选择图片文件。取出文件名。
验证上传的是否是图片文件。photoValid:检查文件名是以JPG,JEPG,PNG结尾。
5,使用jQuery获取图片文件的内容。
6,processImageFile:处理图片的内容。传入图片文件的内容,把内容读成数据,读到内存,读到img标签,读到Java代码。
7,通过css把图片数据显示出来。把图片数据设置到隐藏的 input。

 $("#file").change(function (evt) {
        let f = $('#file').val()
        if (_os.photoValid(f)){
            
            let file = $("#file").get(0).files[0]
            
            _os.processImageFile(file,function (r) {
                $("#imagePreview").css('background-image','url('+r.image+')');
                $("#imagePreview").show();
                $("#recommendPicture").val(r.data)
            })
        }

    })

8,提交 form 表单,因为图片的数据量大,form表单中使用post提交。

<form id="recommendForm" class="panel-body" action="${base}/mergeRecommend" method="post">       
$("#recommendForm").submit()

二,完成图片资源的入库。
recommend picture 栏的数字= attachment的id,可以获取到对应的attachment数据
在这里插入图片描述
在这里插入图片描述

获取到attachment的 resourceId,获取到resource,获取到resource的content。
在这里插入图片描述
在这里插入图片描述

1,controller中接收前端提交的图片数据,判断前端有没有提交图片数据。有提交图片的数据:就调用方法,创建图片的资源表,附件表。方法中传入图片的数据,和哪个单元上传的图片来源名称,返回图片附件表的id。将 id 设置到对应的添加或修改的对象。

 if (StringUtils.isNotBlank(recommendPicture)){
            Long atId = attachmentService.createAttachment("recommendPicture",recommendPicture);
            entity.setPicture(atId.toString());
        }

2,在事务中创建图片的资源表,附件表。
HashUtils 获取图片的Hash值。(每一张图片的数据都有独一无二的hash值。) getByHash 查询数据库的图片资源表,判断图片资源是否已存在于数据库。不存在就创建图片资源表的数据。

	@Transactional
	public Long createAttachment(String name,String recommendPicture){
		String hash = HashUtil.sha256(recommendPicture);
		Resource r = resourceDao.getByHash(hash);
		
		if (null == r){
			r = new Resource();
			r.setId(IdUtil.nextId());
			r.setEncoding("Base64");
			r.setHash(hash);
			r.setContent(recommendPicture);
			r.setCreateAt(new Date());
			r.setUpdateAt(new Date());
			this.resourceDao.create(r);
		}

使用domain创建数据库表的数据。创建图片的资源表resource表的数据:
图片资源的id使用 IdUtils 自动生成。
编码格式使用Base64编码。
设置图片资源的hash值。
前端传过来的图片数据作为图片内容。
设置当前时间,作为创建和更新图片资源的时间。
create方法创建图片资源表数据。

3,创建图片资源的附件表。
由于前端提交过来的图片数据都是经过编码的,所以要对图片的数据进行解码,返回到char数组中,使用base64对图片数据解码。
ImageUtils 读取解码后的图片数据。图片的宽高,大小数据,返回到 ImageBean 中。
使用domain创建数据库表的数据。创建图片资源附件表attachment表。设置attachment表字段的值。create方法创建图片附件表的数据,返回attachment的id。

byte[] data = Base64.getDecoder().decode(recommendPicture);
		ImageBean bean = ImageUtil.readImage(data);
		Attachment a = new Attachment();
		a.setResourceId(r.getId());
		a.setUserId(0L);
		a.setName(name);

		a.setHeight(bean.height);
		a.setWidth(bean.width);
		a.setMime(bean.mime);
		a.setSize(bean.size);

		a.setCreateAt(new Date());
		a.setUpdateAt(new Date());
		this.entityDao.create(a);

		return a.getId();
	}

ImageBean封装图片宽高大小格式的数据。

public class ImageBean {

	public BufferedImage image;
	public int width;
	public int height;
	public int size;
	public String mime;
	
}

4,在controller中判断没有图片数据传过来时,为什么不把图片的数据设为0?

 	@RequestMapping("/mergeRecommend")
    public ModelAndView mergeRecommend(Recommend entity,String recommendPicture){
    
    	//修改以后重定向到课程推荐页面
        ModelAndView mv = new ModelAndView("redirect:/manage_recommend");
        
        //处理图片的数据
        if (StringUtils.isNotBlank(recommendPicture)){
            Long atId = attachmentService.createAttachment("recommendPicture",recommendPicture);
            entity.setPicture(atId.toString());
        }
        
        //保存修改或添加的数据到数据库
        if(null == entity.getId()){
            if (StringUtils.isBlank(recommendPicture)){
                entity.setPicture("0");
                this.recommendService.create(entity);
            }
        }else {
            this.recommendService.update(entity);
        }
        return mv;
    }

因为修改时也可以不修改图片的数据,也没有图片的数据传过来,这样设置会把原先上传好的图片直接改掉,判断创建时不允许picture为空就可以了。

5,两种方式可以实现图片的加载,需不需要 ${base} 容易搞混

<img id="imagePreview" src="${base}/file/attachment/${item.picture!}/m" />                   
<div style="background-image: url('/file/attachment/${item.picture!}/m');background-size: contain"></div>

三,定义一个公共的,加载项目所有图片的controller,FileController。
1,FileController介绍:
id 的正则表达式:对传入的 picture 数字作限制。[0-9] 表示传入的内容必须是数字,{1~17} 表示有1 至17位数字。
通过get请求,请求(“/file/attachment/” + ID + “/0”)地址,可以直接请求到图片,在相应的位置上写上对应的url地址,就可以把图片显示出来。
但是在修改时获取图片内容,要做 if 判断,判断图片数据是否存在且不等于0。因为创建时不允许picture为空,如果用户没有上传图片,图片数据会设置成0,添加到数据库。或者如果没有图片数据,就展示一个默认的图片。
char类型 size的含义:0原图,m最小图,s小图(有些网站会对图片数据做压缩)
通过responseIO流,把图片输出出来,有输出流要抛 IOE异常。
直接拷贝使用。

@Controller
public class FileController {

    protected static final  String ID = "{id:[0-9]{1,17}}";

    @Autowired
    AttachmentService attachmentService;

    //原图
    @GetMapping("/file/attachment/" + ID + "/0")
    public void process0(@PathVariable("id")long id, HttpServletResponse response) throws IOException {
        process(id,'0', response);
    }

    void process(long id, char size, HttpServletResponse response) throws IOException{
        DownloadBean bean = attachmentService.downloadAttachment(id,size);
        response.setContentType(bean.mime);
        response.setContentLength(bean.data.length);
        response.setHeader("Cache-Control", "max-age=" + 3600*24*30);
        ServletOutputStream output = response.getOutputStream();
        output.write(bean.data);
        output.flush();
    }
}        

在process中,调用获取图片加载数据和格式的方法。设置输出的内容格式,内容长度,对内容做缓存,减少对服务器流量的影响。通过 outputStream 输出图片的数据,刷新,实现图片的加载。

2,如何获取图片加载的数据和格式

downloadBean 封装图片加载的数据和格式。

public class DownloadBean {

	public final String mime;
	public final byte[] data;

	public DownloadBean(String mime, byte[] data) {
		this.mime = mime;
		this.data = data;
	}
DownloadBean bean = attachmentService.downloadAttachment(id,size);

通过请求过来的 picture 数字,也就是attachment的id,可以获取到对应的 attachment 数据。
根据 attachment 的 resourceId,获取到 resource,获取到resource的content,对resource的content做解码。
获取的过程中可能会出现读取图片的异常,用自定义的异常类,APIException,使用 ApiErro 检测用户上传的是不是图片内容。
获取到attachment中图片的格式,和解码的图片资源数据,返回一个封装的downloadBean。

public DownloadBean downloadAttachment(Long id,char size){
		Attachment a = entityDao.getById(id);
		if (null == a){
			throw new ApiException(ApiError.PARAMETER_INVALID,"id","resource is not found");
		}
		Resource r = resourceDao.getById(a.getResourceId());
		if (null == r){
			throw new ApiException(ApiError.PARAMETER_INVALID,"id","resource is not found");
		}
		byte[] data = Base64.getDecoder().decode(r.getContent());

		if(size == '0'){
			return new DownloadBean(a.getMime(),data);
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值