精华内容
下载资源
问答
  • 11、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean区别,StatefulBean和StatelessBean区别。 EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。 SessionBean...
  • 通过将理论融入数据库实践,清晰地讲解了关系型数据库的设计原则,完整地展示了如何进行良好的关系型数据库设计,深入揭示了 sql server 2008的技术细节。.  本书浓缩了作者作为 sql server数据库架构师多年来丰富...
  • 公司提出需要一个文库用来存放文档,并且要求可以全文检索,还要和自己系统权限集成,部分文件还要求保密,打水印、不让复制、不让下载等等各种个性化、奇葩需求,然后发现现成工具要么功能不满足,要么要...

    solr版本:8.4.1

    springboot版本:2.3.0.RELEASE

    pdf.js:2.2.228

    服务器环境:centos

     

    使用场景

    公司提出需要一个文库用来存放文档,并且要求可以全文检索,还要和自己的系统权限集成,部分文件还要求保密,打水印、不让复制、不让下载等等各种个性化的、奇葩的需求,然后发现现成的工具要么功能不满足,要么要花钱,没有一个可以满足老板的要求。

    具体实现步骤

    首先,我们考虑一下要用到的技术:全文检索、文件操作。

    • 全文检索有很多种可以选,那么我们考虑的时候就希望选一种最简单的,非常幸运的是solr和tika有集成插件。tika可以帮我们提取pdf的内容,当然不嫌麻烦的话可以自己去提取pdf的内容,自己提取的话虽然有点麻烦但是数据会更符合自己的使用场景需求。

    • 文件操作方面主要是给文件加水印和前端渲染,浏览器虽然可以直接渲染PDF但是不能实现搜索文本标亮,和定位。那么我选了pdf.js,主要也是因为可以偷懒。官方给的例子稍微改一下完全可以满足使用。

    其次,考虑一下流程,在什么时候给文件加水印呢?我当时的流程如下:

    从上图看得出,这里面我们自己编写的代码其实不多,实现效果如下:

     

    操作步骤:

    1.配置solr插件:抄袭借鉴solr-8.4.1/example/example-DIH/solr/tika文件价内的配置

    重点关注一下:solrconfig.xml里面的

    <requestHandler name="/dataimport" class="solr.DataImportHandler">
        <lst name="defaults">
          <str name="config">tika-data-config.xml</str>
        </lst>
      </requestHandler>

    看得出来是让我们把里面的内容好好抄袭借鉴一下。

    tika-data-config.xml
    
    <dataConfig>
      <dataSource type="BinFileDataSource"/>
      <document>
        <entity name="file" processor="FileListEntityProcessor" dataSource="null"
                baseDir="${solr.install.dir}/example/exampledocs" fileName=".*pdf"
                rootEntity="false">
    
          <field column="file" name="id"/>
    
          <entity name="pdf" processor="TikaEntityProcessor"
                  url="${file.fileAbsolutePath}" format="text">
    
            <field column="Author" name="author" meta="true"/>
            <!-- in the original PDF, the Author meta-field name is upper-cased,
              but in Solr schema it is lower-cased
             -->
    
            <field column="title" name="title" meta="true"/>
            <field column="dc:format" name="format" meta="true"/>
    
            <field column="text" name="text"/>
    	<field column="fileAbsolutePath" name="filePath" />
    	<field column="fileSize" name="size" />
    	<field column="fileLastModified" name="lastModified" />
         </entity>
        </entity>
      </document>
    </dataConfig>
    

    另外需要注意的是字段,managed-schema文件里面默认有几个字段,我配置了一个动态字段来获取pdf的内容,至于原因么,主要还是因为这个可以偷懒

    2.上传文件代码编写

    核心代码例子如下,重点是 attr_这里面会拿到所有需要的字段,path是上传后文件的路径,参数bytes是上传后的文件流转换的,另外我这里配置了solr自动id,不然还需要加一个literal.id

    public void indexFilesByTika(byte[] bytes,String path) throws IOException, SolrServerException {
            ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract");
            String contentType = "application/pdf";
            ContentStreamBase cs = new ContentStreamBase.ByteArrayStream(bytes,document.getFileName());
            cs.setContentType(contentType);
            up.addContentStream(cs);
            up.setParam("literal.path", path);
            up.setParam("uprefix", "attr_");
            up.setParam("fmap.content", "text");
            up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);
            solrClient.request(up);
       }

    3.查询数据

    这时候需要注意的是水印,这个也很简单用itextpdf就可以了

            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.13</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext-asian</artifactId>
                <version>5.2.0</version>
            </dependency>
    
    
    	/**
    	 * 
    	 * @param text 水印文字
    	 * @param url 文件URL
    	 * @param os 输出流
    	 * @param widthExtra 水印的宽
    	 * @param heightExtra 水印的高
    	 * @throws DocumentException
    	 * @throws IOException
    	 */
    	public static void waterMark(String text, URL url, OutputStream os,int widthExtra,int heightExtra) throws DocumentException, IOException {
    		PdfReader reader = new PdfReader(url);
    		// 加完水印的文件
    		PdfStamper stamper = new PdfStamper(reader, os);
    		float width = reader.getPageSize(1).getWidth() / widthExtra;
    		float height = reader.getPageSize(1).getHeight() / heightExtra;
    		int total = reader.getNumberOfPages() + 1;
    		PdfContentByte content;
    		BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
    		for (int i = 1; i < total; i++) {
    			content = stamper.getOverContent(i);
    			content.saveState();
    			PdfGState gs = new PdfGState();
    			gs.setFillOpacity(0.2f);// 设置透明度为0.2
    			content.setGState(gs);
    			for (int j = 0; j < height; j++) {
    				for (int j2 = 0; j2 < width; j2++) {
    					content.beginText();
    					content.setColorFill(BaseColor.BLUE);
    					content.setFontAndSize(font, 24);
    					content.showTextAligned(Element.ALIGN_RIGHT, text, (float)widthExtra * j2, (float)heightExtra * j, 35);
    					content.endText();
    				}
    			}
    
    			content.restoreState();
    		}
    		stamper.close();
    	}
    

    4.前端页面接收与渲染

    修改pdf.js官方的例子,viewer.html,这里主要是改了渲染的方式,官方例子的渲染方式是通过文件渲染,修改后可以通过接口返回的二进制流渲染

    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <meta name="google" content="notranslate">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>PDF.js viewer</title>
    
    
        <link rel="stylesheet" href="viewer.css">
    
    
        <!-- This snippet is used in production (included from viewer.html) -->
        <link rel="resource" type="application/l10n" href="./locale/locale.properties">
        <script src="../build/pdf.js"></script>
        <script src="jquery.min.js"></script>
    
        <script>
           
    
            function convertDataURIToBinary(dataURI) { //编码转换
                var raw = atob(dataURI);
                var rawLength = raw.length;
                var array = new Uint8Array(new ArrayBuffer(rawLength));
                for (i = 0; i < rawLength; i++) {
                    array[i] = raw.charCodeAt(i);
                }
                return array;
            }
            var DEFAULT_URL;
            var param = {};
            param.id = getQueryString("id");
            if (param.id != null) {
                var PDFData = "";
                var BASE64_MARKER = ';base64,';
                $.ajax({
                    url: '接口' + param.id,
                    type: "get",
                    async: false,
                    headers: {
                        'token': '123456'
                    },
                    contentType: "application/pdf;charset=utf-8",
                    beforeSend: function (request) {},
                    success: function (data) {
                        if (data.status == 1) {
                            DEFAULT_URL = convertDataURIToBinary(data.data);
                        }
                    }
                });
            }
        </script>
    
        <script src="viewer.js"></script>
    
    </head>

    至于怎么实现禁止复制黏贴和调用自身的find方法这个,请自己研究吧,最简单的方法就是通过禁用鼠标右键和键盘上一些组合键来实现禁止复制黏贴,找到viewer.js里面的搜索框方法和viewer.html的搜索框代码,在页面渲染结束后赋值再调用搜索方法。有点麻烦但是并不是很难。

    展开全文
  • smarty模版技术

    2019-07-14 17:21:46
    当HTML不可避免要写入数据时 不让PHP便签显示在HTML代码中 从而让代码看上去更整洁 利用特定占位符放到一个文档(HTML)中占据某个位置然后利用相应数据替代占位符 ***本质***本质就是在HTML中设置相对简洁...

    当HTML不可避免的要写入数据时 不让PHP便签显示在HTML代码中 从而让代码看上去更整洁
    利用特定的占位符放到一个文档(HTML)中占据某个位置然后利用相应的数据替代占位符
    ***本质***本质就是在HTML中设置相对简洁的标签 然后利用PHP实现内容的替换.
    下载 官网
    解压 解压之后我们只需要其中libs文件夹下的内容 全选 复制到根目录 可以新建一个vendors文件夹把内容黏贴进去
    plugins文件夹 开发人员插件
    syspluanins 系统插件文件夹
    autoload.php smarty内部增加文件
    smarty.class.php smarty核心入口文件
    smartyBL.class.php smarty兼容入口文件
    优缺点
    效率高 编译型 缓存 插件 灵活(内置函数)
    但是实时效率低 所以一些实时性很强那个的项目例如股票等 不可以使用smarty模板
    编译型 不推荐小项目使用
    smarty是一种致力于解决PHP和HTM L分离的模板引擎

    <html>
        <header></header>
        <body>
            <!--smarty定义占位符-->
            {$hello}
        </body>
    </html>
    
    <?php
    #加载smarty.class.php核心入口文件
    include_once "./vendors/smarty.class.php";
    #实例化对象
    $s = new smarty();
    #定义数据
    $hello = "helloworld smarty";
    #assign方法 
    $s->assign('hello',$hello);
    //第一个参数是占位符 不带$ 第二个参数是具体要传入的数据
    //数据交给smaety系统
    $s->display('./template/01smarty.html');
    ?>
    

    加载 smarty.lass.php文件
    实例化对象 后面会使用到对象的方法和属性
    模版文件中定义占位符 {$变量名}
    assign 第一个参数’变量名 第二个参数 具体数据
    display 加载模板并显示出来
    使用
    smarty之后系统会自动在根目录生成一个template_c文件夹 用来存放编译后的混合文件
    配置
    samety支持在PHP文件中对smarty进行配置 利用对象的属性

    <?php
    #加载smarty.class.php核心入口文件
    include_once "./vendors/smarty.class.php";
    #实例化对象
    $s = new smarty();
    #配置模版默认文件夹
    $s->template_dir='./template/';
    #定义数据
    $hello = "helloworld smarty";
    #assign方法 
    $s->assign('hello',$hello);
    //第一个参数是占位符 不带$ 第二个参数是具体要传入的数据
    //数据交给smaety系统
    //$s->display('./template/01smarty.html');
    $s->display('01smarty.html');
    ?>
    

    模版变量
    smarty的本质就是在PHP文件中用值替换掉模版中用变量表示的占位符
    smarty支持以下几种变量
    PHP分配变量
    最常用的 当时标量数据时直接分配 直接使用
    数据数据时 传入数据 靠下标访问
    对象数据时 传入对像 靠对象->访问

    <?php
    include_once "./vendors/smarty.class.php";
    $s = new smarty();
    $s->template_dir='./template/';
    $hello = "helloworld smarty";
    $arrtest =array('name'=>'ada','age'=>18,'gender'=>'男');
    class Human{
        public $name = 'class';
    }
    $s->assign('Human',new Human);
    $s->assign('hello',$hello);
    $s->assign('arrtest',$arrtest);
    $s->display('01smarty.html');
    ?>
    <html>
        <header></header>
        <body>
            <!--smarty定义占位符-->
            {$hello}
            <br/>
            姓名:{$arrtest['name']}&nbsp;&nbsp;
            年纪:{$arrtest.age}&nbsp;&nbsp;
            性别:{$arrtest.gender}
            <br/>
            Humanclass is {$Human->name}
            <!--smarty区分大小写-->
        </body>
    </html>
    

    PHP变量的值通过assign方法分配给smaety系统 模版中占位符无论是哪基础数据 数组 还是对象都是{$name}这种形式 只不过数组可以通过 . [] 得到值 对象通过 -> ::得到值
    smarty保留变量
    smarty保留变量对应PHP的预定义变量
    $smarty.get .post .request .cookie .session .serviver .now当前时间戳
    current_dir 当前路径 template模版文件 config配置信息
    smarty保留变量可以访问到对应php预定义变量中的占值

    <?php
    include_once "./vendors/smarty.class.php";
    $s = new smarty();
    $s->template_dir='./template/';
    $_GET['username'] = 'bob';
    $s->display('01smarty.html');
    ?>
    <html>
        <header></header>
        <body>
           <!--测试smarty保留变量-->
           username is {$smarty.get.username}
        </body>
    </html>
    

    自定义变量
    上面两种方式 模版中的值 都是由PHP分配的
    smaety支持直接在模版中分配数据 但是不常用
    {assign var=‘名字’ vlaue='值‘ }

    <html>
        <header></header>
        <body>
           <!--测试smarty自定义变量-->
            {assign var="name" value="condy"}
            自定义变量测试的是{$name}
        </body>
    </html>
    <?php
    include_once "./vendors/smarty.class.php";
    $s = new smarty();
    $s->template_dir='./template/';
    $s->display('01smarty.html');
    ?>
    

    配置文件
    smarty还支持通过加载配置文件来获取变量
    我们在根目录中新建了一个smarty_config目录
    在文件夹中新建了config.txt作为配置文件

    <html>
        <header>{config_load file="../smarty_config/config.txt"}</header>
        <body bgcolor={$smarty.config.bgcolor}>
           <!--测试smarty配置文件-->
        </body>
    </html>
    <?php
    include_once "./vendors/smarty.class.php";
    $s = new smarty();
    $s->template_dir='./template/';
    $s->display('01smarty.html');
    ?>
    
    bgcolor=#FFOOOO;
    

    内置函数
    当在模版中过的数据需要一定的逻辑处理时 smarty模版技术封装了一套支持分支循环的语法格式
    分支结构
    {if 判断语句} 执行语句 { else if} 执行语句 {/if}

    <html>
        <header></header>
        <body>
           <!--测试内置函数 分支结构-->
           {if isset($smarty.get.username)}
           username is {$smarty.get.username}
           {else}
           nono 
           {/if}
        </body>
    </html>
    

    循环结构
    foreach

    <html>
        <header></header>
        <body>
          <!--测试foreach-->
          {assign var="user" value=array(111,222,333,444,555)}
          {foreach from=$user key='k' item='v'}
          {$k}:{$v}<br/>
          {/foreach}
        </body>
    </html>
    

    {foreach from=“数组名“ key=“k” k以后就代表键 item=’'v” v以后就代表值}
    smarty为foreach提供了很多可访问的属性
    $smarty.foreach.foreach名字.属性
    $value@属性
    key 下标 index索引 interation 当前次数 first的首次执行 last最后一次执行 show循环是否执行
    total总次数

    <html>
        <header></header>
        <body>
          <!--测试foreach-->
          {assign var="user" value=array('name','age','gender')}
          <table border=1>
            {foreach $user as $value}
            {if $value@first}第一次执行
                <tr>
                    <th>下标</th>
                    <th>循环次数</th>
                    <th>值</th>
                </tr>
            {/if}
            <tr>
                <th>{$value@index}</th>
                <th>{$value@iteration}</th>
                <th>{$value}</th>
            </tr>
            {/foreach}
            {if $value@show} 循环在执行  数据为{$value@total}{/if}
          </table>
        </body>
    </html>
    

    smarty还为foreach提供了当foreach 遍历的数组没有数据

    {assign var='arr' value=array()}
            {if $value@show} 循环在执行  数据为{$value@total}{/if}
            {foreach from=$arr key='key' item='value'}
            {$key}:{$value}
            {foreachelse}
            没有数据
            {/foreach}
    

    文件包含
    实际开发中会将模版拆分成多个

    <div class='order'>
    <!--菜单部分-->
    </div>
    <html>
    <header></header>
    <body>
    <!--菜单部分-->
    {include file='order.html'}
    </body></html>
    

    主要是利用{include file=dir}包含文件来实现一种分离思想
    外部函数
    当有些业务smarty内置函数无法解决时 smarty提供了一种自己写入代码的机制
    1 系统函数的使用在模版中直接使用
    {strlen('asdasa')}
    2 自定义函数
    先在php文件中定义函数function showa(){ echo 'a';}
    直接在模版中使用{showa()}

    展开全文
  • 从就业与择业的角度来讲,计算机相关专业的大学生从事oracle方面的技术是职业发展中的最佳选择。 其一、就业面广:全球前100强企业99家都在使用ORACLE相关技术,中国政府机构,大中型企事业单位都能有ORACLE技术的...
  • 默认就可以了,但是超频玩者是肯定不会放过任何可以提高性能东西,所以如果你想在这里电脑提升一点性能话,就必须慢慢试验,选择一个适当参数才能计算机达到性能和稳定最佳状态!...
  • 1413 网吧维护\资料\xp实用技巧\消除WindowsXP中的复制乱码 .txt 4825 网吧维护\资料\xp实用技巧\深入了解Windows XP刻录功能.txt 7949 网吧维护\资料\xp实用技巧\目录和文件操作命令.txt 3331 网吧维护\资料\xp...
  • 东南大学、中国科学技术信息研究所、国家图书馆有权保留本人所送交学位论文复印件和电子文档,可以采用影印、缩印或其他复制手段保存论文。本人电子文档的内容和纸质论文内容相一致。除在保密期内保密论文和在...
  • 一个牛人提供GIS源码(很好)

    千次下载 热门讨论 2010-08-25 22:49:21
    由于个人比较自私,所以想法上即使有所创意也大会和大家分享(请见谅),加上自身没有技术,所以个人基本上是宁烂也不实现或者别人实现(是有点自私了)。请原谅我的自私,Google是有创意的,但他的技术壁垒是他人所...
  • 主要研究方向是数据库系统、时间数据库、概念建模、面向对象数据库、Wed建模和本体论数据库模型和语言、DBMS系统实现、检索技术等。  Shamkant B.Navathe 世界知名数据库学者。现任佐治亚理工学院计算学院...
  • 你可以查看这篇 Advancing the realtime web 得到更多RethinkDB计划的技术细节。什么时候RethinkDB是一个好的选择?当你的应用很大程度上有赖于数据的实时反馈时,RethinkDB 就会成为一个很棒的选择。“查询-响应”...
  •  ACADVBA代码复制到浩辰CAD中,使用查找替换,将“Acad”替换为“Gcad”,保存为VBI文件后即可加载运行。  3. Vlisp代码兼容性改进  支持90%以上vlisp函数。  4.Vlisp运行代码级(vlx、fas)兼容  可...
  • 技术实现,主要是对方案设计具体实现落地,这个过程会包括完整实现源码以及所有核心代码讲解。保证大家在学习过程中也能完成中间件设计和开发。 测试验证,每一个中间件实现都有一个对应测试工程,...
  • 迟到中文 WebFont

    2021-01-11 03:22:57
    而从技术的角度来说这样合理,但设计师非常坚持,这时候你怎么办?” “我会给设计师讲解工程上面临问题,争取他理解。例如:如果文本使用图片,以腾讯站点访问量来说&#...
  • 本书是一部独具特色面向对象技术著作。书中结合代码示例生动透彻地讲述了面向对象思想精髓,读者真正学会以对象方式进行思考。此外,本书还讨论了各种与面向对象概念密切相关应用主题,包括XML、UML建模语言...
  • 本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作典型应用和...
  • 本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作典型应用和...
  • realplayer

    2010-08-18 10:57:02
    b) 您同意仅按照与此软件和文档的使用权限相适用法律(包括但限于有关版权和其它知识产权相关限制)所规定方式来使用此软件和文档。 c) 仅将此“软件”用于个人或非商业目的。 得以任何方式使用此软件...
  • 本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作...
  • 本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作...
  • ECSHOP使用目前流行AJAX技术,为您实现简洁修改,奠定了基础。 同时在更多方面以减轻用户劳动,提供工作效率为宗旨,完整的实现了相关功能AJAX化,由于是在底层完全支持,所以也为以后扩展打下了基础。 4...
  • 在书籍中,创建一个文档标识为summary.md的文档(大小写敏感) 在文档中,填充无序列表markdown内容,如: <bookstack-summary></bookstack-summary> * [第0章. 前言]($ch0.md) * [第1章. 修订记录]...
  • 本书目的就是帮助读者了解c++是如何支持编程技术的,使读者能从中获得新理解,从而成为一名优秀编程人员和设计人员。适合做高校面向对象编程课程教科书,也可作为c++爱好者参考书。 [center] [a href=...
  • asp.net知识库

    2015-06-18 08:45:45
    技术基础 ...(技术实现总结) 知识集锦:三分钟全面了解 Blog 和 RSS C#+ASP.NET开发基于WebRSS阅读器 ASP.NET RSS Toolkit(RSS工具) Serialize Your Deck with Positron [XML Serialization, XSD, C#]...

空空如也

空空如也

1 2 3 4 5 6
收藏数 111
精华内容 44
关键字:

文档不让复制的技术实现