从后台读取项目文件在前端iframe中展示

项目中有个需求是:

对于外部提供的前端项目,包含css、js、html、图片等的项目,将这个项目存进数据库,然后iframe中展示html,然后html中引用的js、css等文件

也能从数据库中读取并正确的展现;

所以其实我们这边分为两步:

1)将整个项目,中的所有文件,js、css等都以路径形式存进数据库,路径其实就是js等文件在html中的引用路径;

2)iframe中引用了HTML,然后html中js等文件从数据库读取出来,正确引用;

 

(其中,参考了博客:

https://www.cnblogs.com/notDog/p/5122106.html
主要是获取路径时,想了好久,restful的表达式中可以正则等等。。

)

 

我这边只做了第二步,下面是过程+思路:

假设现在要展现这个项目,前端demo项目:

直接打开mobile_nav.html是能访问的,直接访问结果:

现在要把htmldemo这个项目存进数据库,然后再我们的jsp页面中iframe中引用mobile_nav.html,也能正确展现。

怎么做呢?代码:

1.数据库表格式:

t_fileinfo:

create table t_fileinfo(
zipname varchar2(200),
filepath varchar2(500),
filecontent blob
);

假设htmldemo中的文件都已经被正确存储了:

 

2.showMobile.jsp中创建ifrmae,并引用mobile_nav.html:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>展示iframe中的页面</title>
<style>
    #iframe{
        width: 100%;
        height: 500px;
    }
</style>
</head>
<body>
    <center>展示iframe中的页面,html页面从数据库读取</center>
    <iframe id="iframe" src="${pageContext.request.contextPath}/iframe/htmldemo.zip/mobile_nav.html"/>
</body>
</html>
View Code

 

3.思路是:

  • iframe中src使用路径是:/iframe/包名/路径,根据包名+路径获取文件的二进制流,response根据文件后缀类型设置相应的content-type,
  • html就采用html的contenttype,js文件采用js的contenttype等。。
  • controller中采用restful风格的requestMapping来接受,就能获取到包名、和路径,就能获取文件流了。
  • 值得注意的一点是:iframe里面的文件的引用地址,也会带上/iframe/包名   父路径,这样子页面中的文件引用也能根据包名+路径获取,非常关键。

4.htmlController:

package com.cy.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerMapping;

import com.cy.service.HtmlService;

/**
 * 控制展示iframe中的HTML页面
 * @author CY
 *
 */
@Controller
public class HtmlController {
    private static Logger logger = Logger.getLogger(HtmlController.class);
    
    @Autowired
    private HtmlService htmlService;
    
    /**
     * 对于iframe/path开头的url的处理
     */
    @RequestMapping("/iframe/{zipName}/**")
    public void iframeRequest(@PathVariable("zipName") String zipName, 
            HttpServletResponse response, HttpServletRequest request)
    {
        String filePath = extractPathFromPattern(request);
        
        logger.info("---->>>zipName:"+zipName);
        logger.info("---->>>filePath:"+filePath);
        
        byte[] fileContent = htmlService.getFileContent(zipName, filePath);
        String contentType = htmlService.getContentType(filePath);
        
        //把html等文件写出去;
        response.setContentType(contentType); 
        response.setCharacterEncoding("utf-8");
        
        //有些引用的多余,例如bootstrap/bootstrap.min.css.map、jquery/jquery.min.map就会报空指针异常
        if(fileContent!=null){            
            try{
                InputStream picture = new ByteArrayInputStream(fileContent);
                OutputStream outputStream=response.getOutputStream();
                int len = 0;
                byte[] buf = new byte[1024];
                while((len = picture.read(buf,0,1024)) != -1){
                    outputStream.write(buf, 0, len);
                }
                outputStream.close();  
            }catch (IOException e) {  
                e.printStackTrace();
            }
        }
    }
    
    // 把指定URL后的字符串全部截断当成参数
    // 这么做是为了防止URL中包含中文或者特殊字符(/等)时,匹配不了的问题
    private static String extractPathFromPattern(
                final HttpServletRequest request)
    {
         String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
         String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
         return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }
    
    
    
    /*
    @RequestMapping("/iframe/{zipName}/{filePath:.+}")
    public void iframeRequest(@PathVariable("zipName") String zipName, 
                              @PathVariable("filePath") String filePath, 
            HttpServletResponse response)
    {
        logger.info("---->>>zipName:"+zipName);
        logger.info("---->>>filePath:"+filePath);
        
        byte[] fileContent = htmlService.getFileContent(zipName, filePath);
        
        //把html页面写出去;
        response.setContentType("text/html"); 
        response.setCharacterEncoding("utf-8");
        try{
            InputStream picture = new ByteArrayInputStream(fileContent);
            OutputStream outputStream=response.getOutputStream();
            int len = 0;
            byte[] buf = new byte[1024];
            while((len = picture.read(buf,0,1024)) != -1){
                outputStream.write(buf, 0, len);
            }
            outputStream.close();  
        }catch (IOException e) {  
            e.printStackTrace();
        }
        
    }*/
    
    
    
    
    
    
}

htmlService:

package com.cy.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cy.dao.HtmlMapper;
import com.cy.model.FileInfo;

@Service
public class HtmlService {
    
    @Autowired
    private HtmlMapper htmlMapper;
    
    /**
     * 根据文件zip、文件名、文件path,获取fileContent
     * @return
     */
    public byte[] getFileContent(String zipName, String filePath){
        byte[] b = null;
        
        FileInfo fi = htmlMapper.getFileContent(zipName, filePath);
        if(fi!=null){
            b = fi.getFileContent();
        }
        
        return b;
    }
    
    /**
     * 根据文件后缀名拿到文件的ContentType
     * @param filePath
     * @return
     */
    @SuppressWarnings("serial")
    public String getContentType(String filePath){
        int pos = filePath.lastIndexOf(".");
        String suffix = filePath.substring(pos+1);
        String contentType = "application/octet-stream";    //默认二进制流数据类型;
        
        Map<String, String> contentMap = new HashMap<String, String>(){
            {
                put("html", "text/html");
                put("jpg", "image/jpeg");
                put("png", "image/png");
                put("css", "text/css");
                put("js", "application/x-javascript");
            }
        };
        
        for(Map.Entry<String, String> entry : contentMap.entrySet()){
            if(entry.getKey().equals(suffix)){
                contentType = entry.getValue();
                break;
            }
        }
        
        return contentType;
    }
}
View Code

HtmlMapper:

package com.cy.dao;

import org.apache.ibatis.annotations.Param;
import com.cy.model.FileInfo;

public interface HtmlMapper {
    
    public FileInfo getFileContent(@Param("zipName")String zipName, 
                                    @Param("filePath")String filePath);
}
View Code

HtmlMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cy.dao.HtmlMapper" >
    
    <select id="getFileContent" resultType="com.cy.model.FileInfo">
        select * from t_fileInfo where zipName=#{zipName} and filePath=#{filePath}
    </select>
      
</mapper>
View Code

FileInfo.java:(model):

package com.cy.model;

/**
 * 项目每个文件实体类
 * @author CY
 *
 */
public class FileInfo {
    private String zipName;
    private String filePath;
    private byte[] fileContent;
    
    public String getZipName() {
        return zipName;
    }
    public void setZipName(String zipName) {
        this.zipName = zipName;
    }
    public String getFilePath() {
        return filePath;
    }
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }
    public byte[] getFileContent() {
        return fileContent;
    }
    public void setFileContent(byte[] fileContent) {
        this.fileContent = fileContent;
    }
    
    
}
View Code

 

 

测试:

输入url后,iframe中能正确展示:

 

附:

 

 

posted on 2017-12-11 22:16  有点懒惰的大青年  阅读(1705)  评论(0编辑  收藏  举报