分布式day08

1. 实现文件的上传

1.1 文件上传入门案例

1.1.1 编辑上传页面

提前给大家准备了一个页面,在webapp下名字叫file.jsp的文件,访问local host:8091/file.jsp
在这里插入图片描述

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>实现文件长传</h1>
	<!--enctype="开启多媒体标签"  -->
	<form action="http://localhost:8091/file" method="post" 
	enctype="multipart/form-data">
		<input name="fileImage" type="file" />
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

这里的请求方式(method)不采用get的方式,因为get请求他把0/1存到我们的浏览器中,以后以后缀的形式进行拼接
enctype="multipart/form-data"代表着开启多媒体标签,开启之后我们文件才能进行正常的上传,否则他上传的东西就对当作普通的文本进行操作
我们看一下请求路径,点击选择文件,选择一个图片,然后打开,提交,我们看一下url
在这里插入图片描述

1.1.2 编辑文件上传功能

请求参数类型这里我们可以采用流的方式进行处理,InputStream或者FileInput Stream,但是我们这里有个麻烦的问题,一方面我们对流的操作不熟悉,另一方面我们需要使用完之后关闭流,说白了要记得关闭,不关的话一方面占 用内存,另一方面别人再用的时候可能会出现异常,所以mvc针对文件上传的操作,提供了一个非常好用的接口,接口名叫MultipartFile,MultipartFile下有很多方法其中getOriginalFilename()获取文件真实的名字,transferTo是表示要操作文件上传

package com.hc.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

@RestController//返回数据是一个json
public class FileController {
    /**
     * 业务说明:实现用户文件上传
     * url地址:http://localhost:8091/file
     * 请求参数:fileImage
     * 返回值:表示上传成功的字符串
     * 文件上传的容量:默认条件下是1M
     */
    @RequestMapping("/file")
    public String file(MultipartFile fileImage) throws IOException {
        String dir="D:/JT-SOFT/images";
        File dirFile=new File(dir);
        if(!dirFile.exists()){
            dirFile.mkdirs();//创建多级目录
        }
        //获取文件名称
        String fileName=fileImage.getOriginalFilename();
        //将文件封装为一个完整的路径
        File imageFile=new File(dir+"/"+fileName);
        fileImage.transferTo(imageFile);
        return "文件上传成功";
    }

}

我们的项目上传图片弹出的文本框是谁提供的呢?我们点击批量上传,发现,这个文本框是富文本编辑器给我们的
在这里插入图片描述

1.2 文件上传实现

1.2.1 页面参数分析

1.请求网址
在这里插入图片描述
2.请求参数

在这里插入图片描述
找到common.js找到

在这里插入图片描述
3.返回结果要求
打开华电资料,找到D:\华电新版本资料\华电新版本资料\课上资料-配-文件\3-文件上传-nginx负载均衡\1-富文本编辑器案例\图片回显的json格式,这里面就是上传文件要求我们返回的数据格式

 {"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}

参数说明: 0代表是一张图片,如果是0,前台才可以解析并显示。1代表不是图片,
不显示如果不设置宽度和高度,则默认用图片原来的大小,所以不用设置
1.error=0文件上传成功 error=1 文件上传失败
2.url :图片上传之后的虚拟路径
3.width.height 是我们图片的特有的属性
所以说,我们富文本编辑器里面的key和value是一一对应的,key不变,但是value需要我们自己填写
在这里插入图片描述

1.2.2 封装ImageVO

package com.hc.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO implements Serializable {
    /**
     * 为了保证我们ImageVo对象传递的完整性和可传递性,我们实现下序列化
     * SerialtionsUID 用来表明了类的不同版本间的兼容性
     */
    // {"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}
    private Integer error; //0正常  1错误
    private String url;    //图片的虚拟路径
    private Integer width; //宽度
    private Integer height;//高度

    public static ImageVO fail(){
        return new ImageVO(1,null,null,null);

    }
    public static ImageVO success(String url,Integer width,Integer height){
        return new ImageVO(0,url,width,height);
    }
}

1.2.3 编辑FileController

 /**
     * 业务实现:文件上传实现
     * url地址:http://localhost:8091/pic/upload?dir=image
     * 参数  uploadFile
     * 返回值: ImageVO
     */
    @RequestMapping("/pic/upload")
    public ImageVO uploadFile(MultipartFile uploadFile){
        //return fileService.uploadFile(uploadFile);
        String url="http://img30.360buyimg.com/jgsq-productsoa/jfs/t1/189927/28/12397/178759/60e80002E1313d54d/fc32d9a0b8eb47fb.jpg";
        return ImageVO.success(url, 800, 800);
    }

在这里插入图片描述
写完项目之后,看看效果,我们有一个小bug,就是上传多个图片的时候都一致

业务分析:

/**
  • 文件上传策略:
  • 1.图片类型进行校验 正则表达式
  • 2.检验文件是否有木马 木马.exe.jpg 宽度和高度
  • 3.将文件分目录存储 hash 时间
  • 4.防止文件重名 uuid当名称
  • @param uploadFile
  • @return
    */

1.2.5 正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
我们回到controller这里,因为我们要用正则表达式,所以不需要去取类型,将 String fileType=fileName.substring(fileName.lastIndexOf(".")+1);注释掉

 public ImageVO uploadFile(MultipartFile uploadFile) {
        //1.图片类型校验
        //1.1 获取图片名称
        String fileName=uploadFile.getOriginalFilename();
        //1.2 文件类型判断
//        String fileType=fileName.substring(fileName.lastIndexOf(".")+1);
//        if(!fileType.equals("jpg")){
//
//        }else if(fileType.equals("png")){
//
//        }else if(fileType.equals("png")){
//
//        }
//        switch (){
//            case:
//        }
        //上面的方法很显然是非常非常笨的,而且low
//        if(!typeSet.contains(fileType)){
//            return ImageVO.fail();
//        }
        //虽然这种方式也可以,但是我们可以做的更加简洁
        //jpg png gif....   ABC.jpg java中\\代表\
        if(!fileName.matches("^.+\\.(jpg|png|git)$")){
            return ImageVO.fail();
        }
        System.out.println("文件类型校验成功");
        return null;
    }

重启服务器,访问下页面后

在这里插入图片描述
我们的程序有一个bug

package com.hc.service;

import com.hc.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.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService{
   // private static Set<String> typeSet=new HashSet<>();
    //静态代码块  为成员变量赋值
//    static {
//        typeSet.add("jpg");
//        typeSet.add("png");
//        typeSet.add("gif");
//    }
    private String localDirPath="D:/JT-SOFT/images";   //D:/xxxxx/
    private String urlPath="http://image.jt.com";
    /**
     * 文件上传策略:
     * 1.图片类型进行校验     正则表达式
     * 2.检验文件是否有木马   木马.exe.jpg  宽度和高度
     * 3.将文件分目录存储     hash  时间
     * 4.防止文件重名        uuid当名称
     * @param uploadFile
     * @return
     */
    @Override
    public ImageVO uploadFile(MultipartFile uploadFile) {
        //1.图片类型校验
        //1.1 获取图片名称
        String fileName=uploadFile.getOriginalFilename();
        //1.2 文件类型判断
//        String fileType=fileName.substring(fileName.lastIndexOf(".")+1);
//        if(!fileType.equals("jpg")){
//
//        }else if(fileType.equals("png")){
//
//        }else if(fileType.equals("png")){
//
//        }
//        switch (){
//            case:
//        }
        //上面的方法很显然是非常非常笨的,而且low
//        if(!typeSet.contains(fileType)){
//            return ImageVO.fail();
//        }
        //虽然这种方式也可以,但是我们可以做的更加简洁
        //jpg png gif....   ABC.jpg java中\\代表\    QWE.JPG
        //为了解决操作系统大小写问题 需要讲字符全部小写
        fileName=fileName.toLowerCase();
        if(!fileName.matches("^.+\\.(jpg|png|git)$")){
            return ImageVO.fail();
        }
        //2.是否是恶意程序
        //通过IO流读取文件信息,转化为图片类型
        try {
            BufferedImage bufferedImage=ImageIO.read(uploadFile.getInputStream());
            int height=bufferedImage.getHeight();
            int width=bufferedImage.getWidth();
            if(height==0 || width==0){
                //说明该文件是一个恶意程序
                return ImageVO.fail();
            }
            /**
             * 接下来我们对文件分目录存储,我们可以通过hash函数的方式,常规的hash函数是8个16进制数
             * 我么可以按照截串的方式,2个一截,2个一截,形成4层文件目录  4级
              */
            //3.根据时间动态生成文件目录
            String dateDirPath=new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            //yyyy前面为什么加/ 为了实现路径的拼接
            //3.1 实现本地用户路径的拼接 D:/JT-SOFT/images/2021/07/12/xxxxx.jpg
            String localDir=localDirPath+dateDirPath;

            //3.2 动态生成文件路径
            File dirFile=new File(localDir);
            if(!dirFile.exists()){//动态生成目录
                dirFile.mkdirs();//创建多级目录
            }
            //4.动态的生成用户名称   fc32d9a0b8eb47fb.jpg
            String uuid=UUID.randomUUID().toString().replace("-", "");
            int index=fileName.lastIndexOf(".");
            String fileType=fileName.substring(index);
            String realFileName=uuid+fileType;
            //5.实现文件上传  文件目录、文件名称
            File imageFile=new File(localDir+realFileName);
            uploadFile.transferTo(imageFile);
            //6.虚拟路径拼接
            String url=urlPath+dateDirPath+realFileName;
            return ImageVO.success(url, width, height);

        } catch (IOException e) {
            e.printStackTrace();
            return ImageVO.fail();
        }
    }
}

1.2.4 编辑properties配置文件

说明:由于文件上传的路径和url地址可能发生改变,如果写死到代码里。不便于维护,所以将我们的配置文件信息写到pro里
在manage项目下,properties文件夹下创建一个新的file, image.properties
在这里插入图片描述
在这里插入图片描述

2. 代理机制

2.1 图片代理说明

在这里插入图片描述

2.2 反向代理机制

2.2.1 反向代理说明

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。

2.2.2 反向代理的特点

1.用户不知道访问的服务器到底是谁
2.反向代理是服务器代理(保护了后端服务器数据)
在这里插入图片描述

2.3 正向代理

2.3.1 正向代理介绍

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

2.3.2 正向代理特点

1.用户向代理发送请求,并指定目标服务器(用户清楚自己访问的是谁)
2.正向代理是客户端代理保护了用户的信息
3.正向代理一般是为了实现网络通信(保护了我们用户的信息)

在这里插入图片描述
问题:当我们访问jd.com的时候,我们是反向代理还是正向代理呢?
正向反向都经历了

2.3 Nginx

2.3.1 Nginx介绍

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
特点1:占用内存少 每个线程的启动不超过2M
特点2:并发能力强 5万/秒 2-3万/秒

2.3.2 Nginx的下载/安装

在这里插入图片描述

2.3.3 nginx相关命令

命令执行位置:要求在nginx的根目录下执行
在这里插入图片描述

如何看我们的nginx正常运行了吗?
在这里插入图片描述

2.3.4 关于进程项说明

主进程:主要是提供反向代理服务的
守护进程:防止主进程意外关闭
在这里插入图片描述
1.启动nginx start nginx
2.nginx重启 nginx -s reload -s任务树
3.nginx停止 nginx -s stop

2.4 反向代理入门案例

配置文件conf文件夹下有一个nginx.cof,打开
注意:nginx的所有配置必须在http协议之内完成,否则不生效
每一个server都是一个反向代理的服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值