后台开发中的静态资源映射

 业务场景:

系统上有个磁盘,里面存放了很多文件,有没有什么办法,可以通过 http 请求,快速访问这些文件,最好写一两行代码就能实现。

Tomcat配置

修改 server.xml 配置。
缺点显而易见,但凡知道地址,就可以下载文件,只要愿意,甚至把一整个服务器的文件载下来,因为独立于系统之外,系统内部代码很难限制文件的访问。

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />
           
  <Context path="/rgyx_files" docBase="C:/xxxxx" reloadable="true" crossContext="true"></Context>
</Host>

Nginx

tomcat 与 nginx 某些角度来说,算是对标产品了,tomcat 有的功能 nginx 一般也会有,
因为暂未参与过相关配置,这里提供一下思路,你们自己百度了。

Spring配置方式

这个配置的一般用途是,用于映射 WEB-INF 下的资源文件。其实,mvc:resources 也可以将路径映射到项目外的磁盘目录。

    <mvc:resources mapping="/${mapping_path}/**" location="file:${local_path}/">

    <!-- 系统主题 -->
    <mvc:resources location="/WEB-INF/static/theme/" mapping="/theme/**" />
    <mvc:resources location="/WEB-INF/static/js/" mapping="/js/**" />
    <!-- 通用JS -->
    <mvc:resources location="/WEB-INF/static/lib/" mapping="/lib/**" />
    <!-- 通用资源 -->
    <mvc:resources location="/WEB-INF/static/res/" mapping="/res/**" />
    <!-- LTE 风格管理页面 -->
    <mvc:resources location="/WEB-INF/static/pages/" mapping="/pages/**" />

SpringBoot的配置方式

等价于上述的 Spring 的配置,缺点就是:如果访问的是文件夹,你可能是希望它能返回文件夹的文件列表;对于共享文件,会出现文件无法读取的现象。

    /**
     * 代码样例
     * @param registry -
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/seaboot/file/**").addResourceLocations("file:xxxxxxx");
            logger.debug("开放文件上传资源目录:" + uploadConstant.getRoot());
    }

源代码实现

因为是自己编码实现的,因此,要实现什么样的逻辑,都是可以的。将Url映射到我们的服务器磁盘,然后通过response写入文件即可。

cn.seaboot.common.core的相关代码,一般能在 apache-commons 中找到替代的写法。

如果你非常熟悉下载文件的相关代码,那么就能轻易读懂下面的代码,基本思路,就是从 url 中截取文件信息,然后将文件下载下来。

import cn.seaboot.common.core.CommonUtils;
import cn.seaboot.common.core.FastJsonUtils;
import cn.seaboot.common.file.MimeUtils;
import cn.seaboot.common.file.ResponseWriter;
import cn.seaboot.web.jackson.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

/**
 * 资源映射
 *
 * @author Mr.css
 * @date 2020-09-30 20:01:38
 */
@Controller
@RequestMapping(value = "/sys/resource")
public class ResourceController {
    /**
     * 资源映射
     */
    private Map<String, String> pathMapping = new HashMap<>();

    @PostConstruct
    public void init() {
        pathMapping.put("image", "C:/Users/postm/Desktop");
    }

    @RequestMapping(value = "**", method = RequestMethod.GET)
    public void test(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (!pathMapping.isEmpty()) {
            //start - Url路径截取,只是为了,从Url中获取文件的存储路径(按照自己的想法实现)
            String servletPath = request.getServletPath();
            String mappingPath = servletPath.substring(14);
            int idx = mappingPath.indexOf('/');
            if (idx < 0) {
                idx = mappingPath.length();
            }
            String key= mappingPath.substring(0, idx);
            String path = pathMapping.get(key);
            String value = mappingPath.substring(idx);
            //end --
            File file = new File(path + value);
            if (file.exists()) {
                if (file.isFile()) {
                    //如果是文件,则提供文件的预览功能
                    ResponseWriter.create(request, response)
                        .setPreviewName(file.getName())
                        .write(new FileInputStream(file));
                } else {
                    //如果是文件夹,则列出文件夹下的全部文件,写成JSON数据
                    List<Map<String, Object>> list = genFileList(file);
                    Result result = Result.succeed(list);
                    String json = FastJsonUtils.toJSONString(result);
                    ResponseWriter.create(request, response)
                        .setContentType(MimeUtils.MIME_JSON)
                        .write(json);
                }
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            }
        }
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
    }

    private List<Map<String, Object>> genFileList(File directory) {
        File[] files = directory.listFiles();
        if (CommonUtils.isEmpty(files)) {
            return Collections.emptyList();
        } else {
            List<Map<String, Object>> list = new ArrayList<>(files.length);
            for (File file : files) {
                Map<String, Object> map = new HashMap<>();
                map.put("name", file.getName());
                map.put("length", file.length());
                map.put("lastModified", file.lastModified());
                map.put("canRead", file.canRead());
                map.put("canWrite", file.canWrite());
                list.add(map);
            }
            return list;
        }
    }
}

 效果如下:

通过http请求,就可以获取电脑桌面的全部文件信息。

posted on 2020-10-19 21:26  疯狂的妞妞  阅读(383)  评论(0编辑  收藏  举报

导航