完整项目学习-7

1. 商品修改页面绘制

1.1 编辑页面HTML

//1. 定义页面html
<!-- 定义商品修改的对话框 -->
    <!-- 定义商品修改的对话框 -->
    <el-dialog title="商品修改" :visible.sync="updateDialogVisible" width="60%">
      <!-- 准备修改的表单-->
      <el-form :model="updateItem" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="标题信息" prop="title">
          <el-input v-model="updateItem.title"></el-input>
        </el-form-item>
        <el-form-item label="卖点信息" prop="sellPoint">
          <el-input v-model="updateItem.sellPoint"></el-input>
        </el-form-item>
        <el-form-item label="价格信息" prop="price">
          <el-input v-model="updateItem.price"></el-input>
        </el-form-item>
        <el-form-item label="数量信息" prop="num">
          <el-input v-model="updateItem.num"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="updateDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>
	
	//2. 定义页面JS
	updateDialogVisible: false,
        updateItem: {
    
    },
        //准备一个校验规则
        rules: {
    
    
          title: [
                  {
    
     required: true, message: '请输入商品标题信息', trigger: 'blur' },
                  {
    
     min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur' }
                ],
          sellPoint: [
                  {
    
     required: true, message: '请输入商品卖点信息', trigger: 'blur' },
                  {
    
     min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur' }
                ],
          price: [
                  {
    
     required: true, message: '请输入商品价格信息', trigger: 'blur' },
                  {
    
     min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur' }
                ],
          num: [
                  {
    
     required: true, message: '请输入商品数量信息', trigger: 'blur' },
                  {
    
     min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur' }
                ],
        }

	  //定义JS按钮
	  updateItemBtn(item){
    
    
        	console.log("扩展案例,自己实现 只需要修改 标题/卖点/价格/数量")
        	this.updateDialogVisible = true
        	this.updateItem = item
        	this.updateItem.price = (this.updateItem.price / 100).toFixed(2)
      }

2. 实现商品图片上传

2.1 编辑页面

2.1.1 官网说明

//1. 官网图片JS说明
  <!-- 图片上传的JS
        1. action: 代表图片上传的地址url
        2. file-list: 图片列表数据的集合[{
    
    name:"xx",url:"xxx"},{
    
    }]
        3. 钩子函数: 满足某些条件时触发.
        4. on-preview 当点击已上传列表的信息时触发
        5. on-remove  当移除列表中的图片时触发
      -->
      <el-upload
        class="upload-demo"
        action="https://jsonplaceholder.typicode.com/posts/"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :file-list="fileList"
        list-type="picture">
        <el-button size="small" type="primary">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
      </el-upload>
2. 页面JS补充知识
   handlePreview(){
    
    
      console.log("触发查看函数!!!!")
    },
    handleRemove(){
    
    
      console.log("移除时触发!!!!")
    }

2.1.2 图片上传项目说明

<!--.文件上传组件说明
                1.action: 上传图片地址 http://localhost:8091/xxx/xxx
                2.on-preview 点击图片时触发
                3.on-remove  移除图片时触发
                4.on-success 图片上传成功时触发
                5.multiple   可以支持多张图片上传
                6.drag       是否允许拖拽
              二.请求类型:    一般上传字节信息时,首选post请求
              三.上传文件key  说明: 文件上传时的key=file.
              				 后端接收数据时采用file接收.
            -->
            <el-upload class="upload-demo" :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove"
              :on-success="handleSuccess" list-type="picture" multiple drag>
              <el-button size="small" type="primary">点击上传</el-button>
              <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>

//定义文件上传路径地址
uploadUrl: "http://localhost:8091/file/upload",

2.1.3 图片上传接口文档说明

  • 请求路径: http://localhost:8091/file/upload
  • 请求类型: post
  • 请求参数:
参数名称 参数说明 备注
file 文件上传的参数名称 file中携带的是二进制信息
  • 返回值结果:
参数名称 参数说明 备注
status 状态信息 200表示服务器请求成功
msg 服务器返回的提示信息 可以为null
data 服务器返回的业务数据 返回ImageVO对象
  • ImageVO对象说明
参数名称 参数类型 参数说明 备注
virtualPath String 图片实际路径 不包含磁盘信息 例如: 2021/11/11/a.jpg 不需要写磁盘地址
urlPath String 图片url访问地址 http://image.jt.com/2021/11/11/a.jpg 需要指定域名地址
fileName String 文件上传后的文件名称 UUID.type

2.1.4 编辑ImageVO

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {
    
    

    private String virtualPath; //图片虚拟路径 动态的路径
    private String urlPath;  //图片回显的URL地址
    private String fileName; //文件上传后的文件名称
}

2.1.5 编辑ItemController

@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {
    
    

    /**
     * 业务说明: 实现图片上传
     * URL: http://localhost:8091/file/upload
     * 类型: post
     * 参数: file 字节信息
     * 返回值: SysResult.success()
     * 扩展:
     *      一般情况下:
     *          一般前端向后端服务器发送字节信息.由外到内实现数据传输.
     *      采用输入流信息. InputStream file
     *          使用字节流的弊端: 1.必须手动关闭, 2.代码操作繁琐
     *          底层代码的实现.
     *       SpringMVC高级API  MultipartFile 专门处理IO流操作
     *  文件上传步骤:
     *        1.获取文件名称
     *        2.准备文件上传的目录
     *        3.判断目录是否存在  存在目录: 实现上传  没有目录:创建目录
     *        4.利用工具API方法,实现文件上传.
     *  注意事项: MultipartFile 默认支持1M的数据
     */
     @PostMapping("/upload")
     public SysResult upload(MultipartFile file) throws IOException {
    
    
        //1.获取文件名称
         String fileName = file.getOriginalFilename();
         //2.准备磁盘地址
         String dirPath = "E:/project3/images/";
         //3.将这个文件目录 封装为File对象
         File dirFile = new File(dirPath);
         //4.判断对象是否存在
         if(!dirFile.exists()){
    
    
            //如果文件目录不存在,则创建目录
             dirFile.mkdirs(); //表示多级目录上传.
         }
         //5.封装文件全路径 E:xxx/xxx/a.jpg
         String path = dirPath + fileName;
         File allFile = new File(path);
         //6.实现文件上传 将IO流按照指定的对象格式进行输出.
         file.transferTo(allFile);
         return SysResult.success();
     }
}

2.2 正则表达式(复习)

2.2.1 正则表达式说明

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
总结: 正则表达式就是一种特殊格式的字符串.校验文本信息的.

2.2.2 匹配不确定次数

在这里插入图片描述

2.2.3 匹配固定次数

在这里插入图片描述

2.2.4 匹配取值区间

在这里插入图片描述

2.2.5 分组匹配

(jpg|png|gif)
在这里插入图片描述

2.2.6 正则案例练习

1.要求匹配电话号码 11位 开头都是1
正则表达式: 1[3-9][0-9]{9}
2.要求匹配邮箱 [email protected]
正则表达式:

^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$

2.3 文件上传实现

2.3.1 编辑FileController

@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {
    
    

    @Autowired
    private FileService fileService;

    /**
     * 业务说明: 实现图片上传
     * URL: http://localhost:8091/file/upload
     * 类型: post
     * 参数: MultipartFile file 字节信息
     * 返回值: SysResult.success()
     * 问题思考:
     *      1.完成图片类型校验 jpg|png|gif....
     *      2.防止恶意程序    a.exe.jpg
     *      3.将图片分目录存储
     *             3.1.按照类型分   理论可以但是得多分配几个
     *             3.2.按照时间划分. yyyy/MM/dd
     *      4.自定义文件名称. 利用UUID充当图片名称.
     */
    @PostMapping("/upload")
    public SysResult upload(MultipartFile file) throws IOException {
    
    

        ImageVO imageVO = fileService.upload(file);
        if(imageVO == null){
    
    
            return SysResult.fail();
        }
        return SysResult.success(imageVO);
    }


    /**
     * 业务说明: 实现图片上传
     * URL: http://localhost:8091/file/upload
     * 类型: post
     * 参数:  file 字节信息
     * 返回值: SysResult.success()
     * 扩展:
     *      一般情况下:
     *          一般前端向后端服务器发送字节信息.由外到内实现数据传输.
     *      采用输入流信息. InputStream file
     *          使用字节流的弊端: 1.必须手动关闭, 2.代码操作繁琐
     *          底层代码的实现.
     *       SpringMVC高级API  MultipartFile 专门处理IO流操作
     *  文件上传步骤:
     *        1.获取文件名称
     *        2.准备文件上传的目录
     *        3.判断目录是否存在  存在目录: 实现上传  没有目录:创建目录
     *        4.利用工具API方法,实现文件上传.
     *  注意事项: MultipartFile 默认支持1M的数据
     */
     /*@PostMapping("/upload")
     public SysResult upload(MultipartFile file) throws IOException {
         //1.获取文件名称
         String fileName = file.getOriginalFilename();
         //2.准备磁盘地址
         String dirPath = "E:/project3/images/";
         //3.将这个文件目录 封装为File对象
         File dirFile = new File(dirPath);
         //4.判断对象是否存在
         if(!dirFile.exists()){
            //如果文件目录不存在,则创建目录
             dirFile.mkdirs(); //表示多级目录上传.
         }
         //5.封装文件全路径 E:xxx/xxx/a.jpg
         String path = dirPath + fileName;
         File allFile = new File(path);
         //6.实现文件上传 将IO流按照指定的对象格式进行输出.
         file.transferTo(allFile);
         return SysResult.success();
     }*/
}

2.3.2 编辑FileService

package com.jt.service;

import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService{
    
    

    private String localDirPath = "E:/project3/images";

    //1.校验图片类型   xxx.jpg   校验后缀是否为jpg
    @Override
    public ImageVO upload(MultipartFile file) {
    
    

        //1.1 获取文件名称  abc.jpg
        String fileName = file.getOriginalFilename();
        //1.2 全部转化为小写字母
        fileName = fileName.toLowerCase();
        //1.3正则校验是否为图片类型
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
    
    
            //图片类型 不匹配  程序应该终止
            return null;
        }

        //2.校验是否为恶意程序 怎么判断就是一张图 高度和宽度
        //2.1 通过图片对象进行处理
        try {
    
    
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if(height == 0 || width == 0){
    
    
                return null;
            }
            //3.将图片分目录存储 yyyy/MM/dd
            String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                .format(new Date());
            String dateDirPath = localDirPath + dateDir;
            File dirFile = new File(dateDirPath);
            if(!dirFile.exists()){
    
    
                dirFile.mkdirs();
            }

            //4.防止文件重名  动态生成UUID.类型
            //4.1 动态生成UUID
            String uuid = UUID.randomUUID().toString()
                              .replace("-","");
            //4.2 获取图片类型        abc.jpg    .jpg
            String fileType = fileName.substring(fileName.lastIndexOf("."));
            // uuid.jpg
            String newFileName = uuid + fileType;

            //5.实现文件上传 1.准备全文件路径  2. 封装对象实现上传
            String path = dateDirPath + newFileName;
            file.transferTo(new File(path));

        } catch (IOException e) {
    
    
            e.printStackTrace();
            return null;
        }

        return null;
    }
}

2.4 文件删除操作

2.4.1 文件删除JS

在这里插入图片描述

2.4.2 文件删除业务接口

  • 请求路径: http://localhost:8091/file/deleteFile
  • 请求类型: delete
  • 请求参数:
参数名称 参数说明 备注
virtualPath 文件上传的虚拟的路径 删除时需要磁盘路径一起删除
  • 返回值结果:
参数名称 参数说明 备注
status 状态信息 200表示服务器请求成功 201表示服务器异常
msg 服务器返回的提示信息 可以为null
data 服务器返回的业务数据 可以为null

2.4.3 编辑FileController

 /**
     * 业务说明: 文件删除操作
     * URL地址:   http://localhost:8091/file/deleteFile
     * 请求类型:   delete
     * 参数:      virtualPath 虚拟路径
     * 返回值:    SysResult对象
     */
    @DeleteMapping("/deleteFile")
    public SysResult deleteFile(String virtualPath){
    
    

        fileService.deleteFile(virtualPath);
        return SysResult.success();
    }

2.4.4 编辑FileService

@Override
    public void deleteFile(String virtualPath) {
    
    
        String filePath = localDirPath + virtualPath;
        File file = new File(filePath);
        if(file.exists()){
    
     //如果文件存在,则删除数据
            file.delete();
        }
    }

2.5 图片路径封装

2.5.1 路径分析

  1. 图片网络地址: https://img14.360buyimg.com/n0/jfs/t2/ac4a3f32ea776da3.jpg
    协议://域名:80/虚拟地址
  2. 图片地址封装: http://image.jt.com:80/2021/11/11/uuid.jpg.

2.5.2 页面URL地址封装

package com.jt.service;

import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService{
    
    

    private String localDirPath = "E:/project3/images";
    private String preUrl = "http://image.jt.com";

    //1.校验图片类型   xxx.jpg   校验后缀是否为jpg
    @Override
    public ImageVO upload(MultipartFile file) {
    
    

        //1.1 获取文件名称  abc.jpg
        String fileName = file.getOriginalFilename();
        //1.2 全部转化为小写字母
        fileName = fileName.toLowerCase();
        //1.3正则校验是否为图片类型
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
    
    
            //图片类型 不匹配  程序应该终止
            return null;
        }

        //2.校验是否为恶意程序 怎么判断就是一张图 高度和宽度
        //2.1 通过图片对象进行处理
        try {
    
    
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if(height == 0 || width == 0){
    
    
                return null;
            }
            //3.将图片分目录存储 yyyy/MM/dd
            String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                .format(new Date());
            String dateDirPath = localDirPath + dateDir;
            File dirFile = new File(dateDirPath);
            if(!dirFile.exists()){
    
    
                dirFile.mkdirs();
            }

            //4.防止文件重名  动态生成UUID.类型
            //4.1 动态生成UUID
            String uuid = UUID.randomUUID().toString()
                              .replace("-","");
            //4.2 获取图片类型        abc.jpg    .jpg
            String fileType = fileName.substring(fileName.lastIndexOf("."));
            // uuid.jpg
            String newFileName = uuid + fileType;

            //5.实现文件上传 1.准备全文件路径  2. 封装对象实现上传
            String path = dateDirPath + newFileName;
            file.transferTo(new File(path));

            //6. 实现ImageVO数据的返回
            //6.1 准备虚拟路径 /2021/11/11/uuid.jpg
            String virtualPath = dateDir + newFileName;
            //6.2 准备URL地址  域名前缀 + 虚拟路径
            String url =  preUrl + virtualPath;
            System.out.println(url);
            return new ImageVO(virtualPath,url,newFileName);
        } catch (IOException e) {
    
    
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void deleteFile(String virtualPath) {
    
    
        String filePath = localDirPath + virtualPath;
        File file = new File(filePath);
        if(file.exists()){
    
     //如果文件存在,则删除数据
            file.delete();
        }
    }
}

2.6 动态为属性赋值

2.6.1 业务需求

说明: 如果将属性写死到java类中,后期维护时 导致维护不方便.
优化: 可以通过@value注解动态赋值.
在这里插入图片描述

2.6.2 编辑properties配置文件

image.localDirPath=E:/project3/images
image.preUrl=http://image.jt.com

2.6.3 属性动态赋值

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43770110/article/details/121341058