• Spring Boot 静态资源映射与上传文件路由配置


    默认静态资源映射目录

    默认映射路径

    在平常的 web 开发中,避免不了需要访问静态资源,如常规的样式,JS,图片,上传文件等;Spring Boot 默认配置对静态资源映射提供了如下路径的映射 /static (or /public or /resources or /META-INF/resources) ,如下:

    /META-INF/resources/
    classpath:/resources/
    classpath:/static/
    classpath:/public/

    可以在源码中可以查看到

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/",  "classpath:/static/", "classpath:/public/" };

    当然可以通过配置的方式自定义静态资源的路径,但是会覆盖默认约定的映射目录(默认的配置不可用)

    # Locations of static resources.
    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

    一般情况没有特殊需求不建议自定义配置,使用默认的就好,约定大于配置嘛。也就是在 resources 目录下 public、resources、static(新建项目自带) 三个目录。

    默认访问路由

    静态资源的默认路由匹配 /** , 路由会从这三个目录中寻找静态资源,如果有则返回,当然可以配置改变默认的路由,如下:

    spring.mvc.static-path-pattern=/resources/**

    OK,我新建了一个项目,结构目录如下:

    image

    比如在 static 目录下新增一个 MP_verify_46Daxcm7OmhjBcYa.txt 文本文件,浏览器访问 http://localhost:8080/MP_verify_46Daxcm7OmhjBcYa.txt 即可,引用 css,js ,图片等资源也不需要再加 static 目录了。

    自定义静态资源映射目录

    自定义静态资源映射目录可以通过上述配置的方式配置,当然也可以通过编码的方式实现

    WebConfig

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            //将访问/static/** 的路由映射到classpath:/static/ 目录下
            registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        }
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
            registry.addViewController("/groovy").setViewName("hello");
            registry.addViewController("/app").setViewName("app");
        }
    }

    上传文件映射路径配置

    默认 Spring Boot 是内置了 Tomcat 以单个 Jar 包的运行(当然也可以使用 war 包的方式运行在容器里),Spring Boot 项目启动的时候会跟根据约定把静态文件加载到 classpath 目录下,如果要上传文件或写文件日志的话,必须把访问的路由映射到服务器的文件目录。

    FileUploadController
        private final ResourceLoader resourceLoader;  
      
        @Autowired  
        public UploadController(ResourceLoader resourceLoader) {  
            this.resourceLoader = resourceLoader;  
        }  
    
        /**
         * 上传文件
         * @param file
         * @param model
         * @param request
         * @return
         */
        @RequestMapping(method = RequestMethod.POST, value = "/")  
        public String upload(@RequestParam("file") MultipartFile file, Model model, HttpServletRequest request) {  
            if (!file.isEmpty()) {  
                try {  
                    Files.copy(file.getInputStream(), Paths.get("/upload", file.getOriginalFilename()));  
                    model.addAttribute("message",  "You successfully uploaded " + file.getOriginalFilename() + "!");  
                    } catch (IOException|RuntimeException e) {  
                        model.addAttribute("message", "Failued to upload " + file.getOriginalFilename() + " => " + e.getMessage());  
                    }  
                } else {  
                    model.addAttribute("message", "Failed to upload " + file.getOriginalFilename() + " because it was empty");  
                }  
                return "redirect:/";  
            }  
      }  
        /**
         * 绑定微信用户 (头像图片编码base64)
         * @param weixinBindRequest
         * @param session
         * @return
         */
        @ResponseBody
        @RequestMapping(value = "/uploadImgbase64",method= RequestMethod.POST)
        public WeixinBindResponse uploadImgbase64(@RequestBody WeixinBindRequest weixinBindRequest, HttpSession session) {
            //logger.info("weixinbind req: " + JSON.toJSONString(weixinBindRequest));
            WeixinBindResponse response= new WeixinBindResponse();
            logger.info("weixinbind  openId: "+weixinBindRequest.getOpenid());
            //保存用户头像
            for (int i=0;i<weixinBindRequest.getImgs().length;i++){
                String dataPrix = "";
                String data = "";
                String suffix = "";
                String [] d = weixinBindRequest.getImgs()[i].split("base64,");
                if(d != null && d.length == 2){
                    dataPrix = d[0];
                    data = d[1];
                }
                if("data:image/jpeg;".equalsIgnoreCase(dataPrix)){//data:image/jpeg;base64,base64编码的jpeg图片数据
                    suffix = ".jpg";
                } else if("data:image/x-icon;".equalsIgnoreCase(dataPrix)){//data:image/x-icon;base64,base64编码的icon图片数据
                    suffix = ".ico";
                } else if("data:image/gif;".equalsIgnoreCase(dataPrix)){//data:image/gif;base64,base64编码的gif图片数据
                    suffix = ".gif";
                } else if("data:image/png;".equalsIgnoreCase(dataPrix)){//data:image/png;base64,base64编码的png图片数据
                    suffix = ".png";
                }
                String fileName = weixinBindRequest.getOpenid() +"_"+i + suffix;
                try{
                    //  request.getSession().getServletContext().getRealPath("upload");
                    //  String path = String.valueOf(Paths.get("upload", weixinBindRequest.getOpenid()));
                    FileUtils.writeByteArrayToFile(new File("upload", fileName), Base64Utils.decodeFromString(data));
                }catch(Exception ee){
    
                }
            }
            //微信绑定用户信息
             boolean flag =  this.userSerice.bindWeixinUser(weixinBindRequest);
            if(!flag){
                response.setIsError(true);
                response.setErrorCode(500);
                response.setErrorMsg("微信绑定用户信息失败!!!");
                return response;
            }
            response.setIsError(false);
            response.setErrorCode(200);
            response.setErrorMsg("微信绑定用户信息成功!!!");
            return response;
        }
    
        /**
         * 显示图片
         * @param filename
         * @return
         */
        @RequestMapping(method = RequestMethod.GET, value = "/{filename:.+}")
        @ResponseBody
        public ResponseEntity<?> getFile(@PathVariable String filename) {
            try {
                return ResponseEntity.ok(resourceLoader.getResource("file:" + Paths.get("upload", filename).toString()));
            } catch (Exception e) {
                return ResponseEntity.notFound().build();
            }
        }
    上传文件的路径会项目根目录上创建,所以不能被直接访问到 ,Spring 提供了 ResourceLoader ,利于这个类可以加载非应用目录的里文件然后返回,具体看官方的列子吧: 

    https://spring.io/guides/gs/uploading-files/
    https://github.com/spring-guides/gs-uploading-files.git

    上传文件大小限制

    最后别忘了配置文件大小的限制

    spring.http.multipart.max-file-size=128KB
    spring.http.multipart.max-request-size=128KB

    遇到的问题:

    如果使用了 nginx 代理提示如下错误:

    Troubleshooting “Request Entity Too Large” (HTTP 413) error message returned to browser

    nginx 中配置 client_max_body_size 允许的大小 

    client_max_body_size       100m; 
    client_body_buffer_size    128k;

    配置附录:

    # SPRING RESOURCES HANDLING (ResourceProperties)
    spring.resources.add-mappings=true # Enable default resource handling.
    spring.resources.cache-period= # Cache period for the resources served by the resource handler, in seconds.
    spring.resources.chain.cache=true # Enable caching in the Resource chain.
    spring.resources.chain.enabled= # Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled.
    spring.resources.chain.gzipped=false # Enable resolution of already gzipped resources.
    spring.resources.chain.html-application-cache=false # Enable HTML5 application cache manifest rewriting.
    spring.resources.chain.strategy.content.enabled=false # Enable the content Version Strategy.
    spring.resources.chain.strategy.content.paths=/** # Comma-separated list of patterns to apply to the Version Strategy.
    spring.resources.chain.strategy.fixed.enabled=false # Enable the fixed Version Strategy.
    spring.resources.chain.strategy.fixed.paths=/** # Comma-separated list of patterns to apply to the Version Strategy.
    spring.resources.chain.strategy.fixed.version= # Version string to use for the Version Strategy.
    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # Locations of static resources.

    REFER:
    https://spring.io/blog/2014/07/24/spring-framework-4-1-handling-static-web-resources
    https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-spring-mvc-static-content

  • 相关阅读:
    docker简单介绍----Dockerfile命令
    docker简单介绍----docker仓库的应用
    nginx实现https的配置文件
    docker简单介绍---网络端口管理
    mysql查看实时连接数
    linux 批量测试域名返回码脚本
    docker简单介绍----镜像和容器管理
    香冢
    GitHub 在使用命令行 git push 时报错:The requested URL returned error: 403
    守规矩应该被骂吗?
  • 原文地址:https://www.cnblogs.com/Irving/p/7444036.html
Copyright © 2020-2023  润新知