Springmvc框架-----3 文件上传

目录

1.文件上传的原理

2. 文件上传到本地服务器

3.elementui+vue+axios完成文件上传

4.注册阿里云服务器并将文件上传到OSS

 4.1 申请OSS文件服务

 4.2 在OSS界面上操作文件上传

4.3 申请阿里云的密钥

5.普通文件上传到OSS文件服务器

6. elementui 异步上传OSS服务器

7. 保存用户信息--头像(综合案例)

8.其他注解

9.Springmvc运行流程

总结


1.文件上传的原理

在前端页面,我们可以提交文件,点击提交以后,文件的路径会被传到控制层,然后将这个路径存到数据库中。

        当我们想查询我们添加的文件时,页面会发送请求到控制层,执行查询业务,像数据库中查询我们的文件路径,如果是ajax异步请求,在控制层封装成json数据最后返回到前端页面。
 

Springmvc框架-----3 文件上传_第1张图片

2. 文件上传到本地服务器

(1)引入文件上传的依赖。

   
    
      commons-fileupload
      commons-fileupload
      1.4
    

(2) 创建一个页面

<%--
  Created by IntelliJ IDEA.
  User: w
  Date: 2022/6/9
  Time: 19:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


    <%--
       method: 提交方式 文件上传必须为post提交。
      enctype:默认application/x-www-form-urlencoded 表示提交表单数据
              multipart/form-data:可以包含文件数据

      input的类型必须为file类型,而且必须有name属性
   --%>
    

Springmvc框架-----3 文件上传_第2张图片

 (3)在springmvc中配置文件上传解析器

   
     
          
          
     

(3)创建upload01接口方法

@RequestMapping(value = "/upload01")
    //注意:MultipartFile 参数名必须和中name属性相同
    public String upload01(MultipartFile myfile, HttpServletRequest request) throws  Exception{
        try {
            //获取本地服务器目录的地址
            String path = request.getSession().getServletContext().getRealPath("upload");
            //判断该目录是否存在
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            //把myfile保存到本地服务器中某个文件夹下
            String filename = UUID.randomUUID().toString().replace("-", "") + myfile.getOriginalFilename();//生成随机数 为了让名字不重复
            File target = new File(path +"/"+ filename);
            myfile.transferTo(target);//把myfile转移到目标目录下
        }catch (Exception e){
            e.printStackTrace();
        }
        return  "";
    }

UUID.randomUUID()   

//随机生成一个字符串 这个字符串一定不会重复

下面的也可以   目的都是为了让文件名不重复

Date date = new Date();

 String filename = date.getTime()+ myfile.getOriginalFilename();        //date.getTime() 时间戳

生成不重复的名称

String filename = date.getTime() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));

                                                

3.elementui+vue+axios完成文件上传

(1)页面的布局

<%--
  Created by IntelliJ IDEA.
  User: w
  Date: 2022/6/9
  Time: 20:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    
    
    
    
    
    
    
    


    

注意:elementui中提交文件的表单 中的name属性默认为file。 

(2)后台的接口

    @RequestMapping(value = "/upload02")
    @ResponseBody
    public CommonResult upload02(MultipartFile file,HttpServletRequest request){
        try{

            //获取本地服务器目录的地址
            String path = request.getSession().getServletContext().getRealPath("upload");
            System.out.println(path);
            //判断该目录是否存在
            File file1 = new File(path);
            if(!file1.exists()){
                file1.mkdirs();
            }
            //把file保存到保存到本地服务器某个文件夹下
            String filename = UUID.randomUUID().toString().replace("-","")+file.getOriginalFilename();//设置上传后的文件名称
            System.out.println(filename);
            File target = new File(path+"/"+filename);
            file.transferTo(target);
            //通过访问服务器地址来访问图片
            String data = "http://localhost:8080/Springmvc0609_2/upload/"+filename;
            CommonResult commonResult = new CommonResult(2000,"上传成功",data);
            return commonResult;
        }catch (Exception e){
            e.printStackTrace();
        }
        CommonResult commonResult = new CommonResult(2000,"上传失败",null);
        return commonResult;
    }

注意:前端发送的是axios异步请求,后端必须响应给前端一个json格式数据。@ResponseBody注解为springmvc中的jackson的jar包内置的json转换方法。

4.注册阿里云服务器并将文件上传到OSS

上传到本地服务器的缺点: 如果搭建集群,导致文件无法在集群中共享。 它的解决方法就是把文件专门上传到一个文件服务器上,这些tomcat服务器都操作同一个文件服务器。

Springmvc框架-----3 文件上传_第3张图片

 4.1 申请OSS文件服务

Springmvc框架-----3 文件上传_第4张图片

 4.2 在OSS界面上操作文件上传

(1)创建bucket容器

Springmvc框架-----3 文件上传_第5张图片

  (2)在该bucket中通过网页面板的形式操作该bucket。但是实际开发我们应该通过java代码往bucket中上传文件。

4.3 申请阿里云的密钥

Springmvc框架-----3 文件上传_第6张图片

文件上传到本地服务器的缺点?

1. 当服务器重启,本地服务的文件没了。
2. 搭建服务器集群。A服务器1000, B服务器......... 
    客户第一次上传时访问的是A服务器。
    客户第二次访问文件,访问的是B服务器。

如何解决本地服务器上传的缺点:

(1)自己搭建一个文件服务器。不会重启。维护。

(2) 使用第三方的文件服务器.

5.普通文件上传到OSS文件服务器

(1)引入阿里云的OSS依赖

 Springmvc框架-----3 文件上传_第7张图片


    com.aliyun.oss
    aliyun-sdk-oss
    3.10.2

(2)代码的书写。

前端:

<%--
  Created by IntelliJ IDEA.
  User: w
  Date: 2022/6/10
  Time: 21:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


    

controller: 

Springmvc框架-----3 文件上传_第8张图片

实际开发中,添加新功能时,先创建个测试类,测试成功后再添加到项目上,否则项目会改的一塌糊涂。

@RequestMapping("/upload03")
    public String upload03(MultipartFile myfile,HttpServletRequest request){
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

      
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "LTAI78XQAZq";    //你的密钥
        String accessKeySecret = "qdyZxR0x4Lo";    //密码
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "wzh666";
        //你上传到oss后的名字 会根据日期帮你创建文件夹。
        Calendar calendar=Calendar.getInstance();
        String objectName =calendar.get(Calendar.YEAR)+"/"+(calendar.get(Calendar.MONTH)+1)+"/"+
                calendar.get(Calendar.DATE)+"/"+UUID.randomUUID().toString().replace("-","")+
                myfile.getOriginalFilename();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream =myfile.getInputStream();
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (Exception oe) {

        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        //https://qy151.oss-cn-hangzhou.aliyuncs.com/2022/6/10/20d3d7e6b5bb455cb548675501f7270fgdnj.jpg
        String url="https://"+bucketName+"."+endpoint+"/"+objectName;
        request.setAttribute("imgUrl",url);
        return "success.jsp";
    }

6. elementui 异步上传OSS服务器

 (1)前端

<%--
  Created by IntelliJ IDEA.

  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    
    
    
    
    
    
    
    


    
<%--action:文件上传的路径--%>

(2)后端工具:

package com.wzh.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Calendar;
import java.util.UUID;


public class OSSUtils {

    public static String upload(MultipartFile myfile){
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

        
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "LTAI7";
        String accessKeySecret = "qdyZxbcrhEyw7H";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "wzh666";
        //你上传到oss后的名字 会根据日期帮你创建文件夹。
        String objectName =fileName(myfile);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream =myfile.getInputStream();
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (Exception oe) {

        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        
        String url="https://"+bucketName+"."+endpoint+"/"+objectName;
        return url;
    }

    //获取上传到oss后的名字
    private static String fileName(MultipartFile myfile){
        Calendar calendar=Calendar.getInstance();
        String name=calendar.get(Calendar.YEAR)+"/"+(calendar.get(Calendar.MONTH)+1)+"/"+
                calendar.get(Calendar.DATE)+"/"+ UUID.randomUUID().toString().replace("-","")+
                myfile.getOriginalFilename();

        return name;
    }
}

(3) controller接口

@RequestMapping(value = "/upload")
@ResponseBody
    public String upload11(MultipartFile file){
        String imgUrl = OSSUtils.upload(file);
        return "success.jsp";
    }

7. 保存用户信息--头像(综合案例)

(1)前端的布局

<%--
  Created by IntelliJ IDEA.
  User: w
  Date: 2022/6/10
  Time: 20:27
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    
    
    
    
    


    
立即提交

(2)工具类

package com.wzh.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Calendar;
import java.util.UUID;

/**
 * @ProjectName: springmvc0610_4
 * @Package: com.wzh.utils
 * @ClassName: OSSUtils
 * @Author: 王振华
 * @Description:
 * @Date: 2022/6/10 21:19
 * @Version: 1.0
 */
public class OSSUtils {
    public static String upload(MultipartFile file){
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "LTAI5tBPAR";
        String accessKeySecret = "RtitGXAuK0yDtzfshVct";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "wzh666";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。

        String objectName = filename(file);
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = file.getInputStream();
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        String imgURL = "https://"+bucketName+"."+endpoint+"/"+objectName;
        return imgURL;
    }

    private static String filename(MultipartFile file){
        Calendar calendar = Calendar.getInstance();
        String name = calendar.get(Calendar.YEAR)+"/"+(calendar.get(Calendar.MONTH)+1)+"/"+ calendar.get(Calendar.DATE)+"/"+ UUID.randomUUID().toString().replace("-","")+file.getOriginalFilename();
        return  name;
    }
}

(3)后台代码

package com.wzh.controller;

import com.wzh.entity.User;
import com.wzh.utils.CommonResult;
import com.wzh.utils.OSSUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

/**
 * @ProjectName: springmvc0610_4
 * @Package: com.wzh.controller
 * @ClassName: UserController
 * @Author: 
 * @Description:
 * @Date: 2022/6/10 20:23
 * @Version: 1.0
 */
@Controller
@RequestMapping(value = "/user")
public class UserController {
    @RequestMapping(value = "/avatarUpload")
    @ResponseBody
    public CommonResult upload(MultipartFile file){
        String imgUrl = OSSUtils.upload(file);
        return new CommonResult(2000,"上传成功",imgUrl);
    }

    @RequestMapping(value = "/add")
    @ResponseBody
    public CommonResult add(@RequestBody User user){
        System.out.println(user);
        return new CommonResult(2000,"提交成功",null);
    }

   
}

8.其他注解

@RestController----类上等价于 @Controller+@ResponseBody
    该注解下所有的方法都是返回json数据

 Springmvc框架-----3 文件上传_第9张图片

@RequestMapping: 作用: 把请求路径映射到响应的方法上。 

Springmvc框架-----3 文件上传_第10张图片

 要与action一致

@RequestParam(value = "u"):设置你接受的请求参数名。查询参数

Springmvc框架-----3 文件上传_第11张图片

Springmvc框架-----3 文件上传_第12张图片

 

 @RequestBody:把请求的json数据转换为java对象。从前端到后端

@ResponseBody:把java转换为json数据   从后端转前端

Springmvc框架-----3 文件上传_第13张图片

 @RequestMapping(value = "/addUser",method = RequestMethod.POST)
       method:表示该接口接受的请求方式.不设置可以接受任意请求方式。
       等价于
@GetMapping("addUser"):表示只接受get提交方式的请求 

@PostMapping("addUser"):表示只接受postt提交方式的请求 

上下两者一样的效果

 Springmvc框架-----3 文件上传_第14张图片

Springmvc框架-----3 文件上传_第15张图片

注意:  文件上传必须用post   表单必须是post提交  编码方式必须是二进制编码。

9.Springmvc运行流程

Springmvc框架-----3 文件上传_第16张图片

第一步:用户发送请求到前端控制器(DispatcherServlet)。

第二步:前端控制器请求 HandlerMapping 查找 Handler,可以根据 xml 配置、注解进行查找。

第三步: 处理器映射器 HandlerMapping 向前端控制器返回 Handler

第四步:前端控制器调用处理器适配器去执行 Handler

第五步:处理器适配器执行 Handler

第六步:Handler 执行完成后给适配器返回 ModelAndView

第七步:处理器适配器向前端控制器返回 ModelAndView

    ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View

第八步:前端控制器请求试图解析器去进行视图解析

    根据逻辑视图名来解析真正的视图。

第九步:试图解析器向前端控制器返回 view

第十步:前端控制器进行视图渲染

    就是将模型数据(在 ModelAndView 对象中)填充到 request 域

第十一步:前端控制器向用户响应结果

总结

1. springmvc框架:----可以帮你完成请求参数的封装以及返回json数据和网页跳转。
2. springmvc如何搭建。依赖,配置文件,web.xml
3. springmvc如何接受请求的参数。
      [1]单个参数--方法中生成这个参数名
      [2]多个参数--封装一个java实体类,方法中声明该实体类即可。
      [3]接受的为日期类型参数.在实体的位置@DatetimeFormat 
4. springmvc如何保存数据到网页: request,session ,model
5. springmvc如何响应json数据。
    1.依赖jackson
    2.方法的返回类型为java对象类型并@ResponseBody

6. 全局异常处理.
     创建一个类并使用@ControllerAdvice
     该类中创建异常处理的方法@ExceptionHandler
7. 拦截器:
    1.创建一个拦截器类并实现HandlerInterceptor接口。
    2.重写preHandler方法。写拦截器的业务代码。
    3.注册到springmvc容器上.
    
8. springmvc文件上传.
    (1)本地服务器上传.-------服务重启后文件不见了. 多态服务器无法共享文件。
    (2)上传到OSS服务器。

你可能感兴趣的:(SpringMVC框架,服务器,spring,mvc)