Linux 机器安装nodejs 、puppeteer及踩坑(页面抓取转pdf)

安装一些必备命令

yum -y install wget unzip

node安装

  • 1.获取nodejs

    wget -c https://nodejs.org/dist/v10.16.3/node-v10.16.3-linux-x64.tar.xz
    
  • 2.解压

    tar -xvf node-v10.16.3-linux-x64.tar.xz
    
  • 3.移动文件夹 将文件夹移动到用户目录下,并重命名为node(通常该步骤是便于应用程序使用)

    mv node-v10.16.3-linux-x64 ~/node
    
  • 4.建立软连接

    sudo ln -s ~/node/bin/node /usr/local/bin/node
    sudo ln -s ~/node/bin/npm /usr/local/bin/npm
    
  • 5.添加环境变量 和上步略有重复,不过建议加上

    sudo vi /etc/profile; 
    //特别提醒:如果前文移动目录自定义,这里也要同步修改
    export NODE_HOME=~/node/bin
    export PATH=$NODE_HOME:$PATH
     
    
  • 6.自测

    node -v
    //打印版本号说明安装成功
    

puppeteer安装

node对于路径很看重,因此把模块安装在哪个目录下很关键,否则你的js文件可能因为缺少模块而不能运行

如果完成上述node安装,你的node所在路径应该是/node,之后的包安装都在/node下进行

  • 1.安装

    //确保进入node文件夹下
    cd ~/node 
    //安装puppeteer,不下载chrome
    npm install puppeteer --ignore-scripts --save
    
  • 2.获取chrome

    • 查看所需chrome版本号:版本号可以在node_modules/puppeteer/package.jsonpuppeteer.chromium_revision获得,现在是818858,根据puppeteer需要自行替换,后续用%d代替(必须,否则puppeteer特性可能不支持)|版本中也许不存在版本信息,先下载上,自测中会提示需要的版本
    wget -c 'https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/818858/chrome-linux.zip'
    

已经下载好 链接:https://pan.baidu.com/s/1c0pKDeqCmt0UIFAf6TncDA
提取码:gs26

  • 3.将chrome放在指定目录下

    cd node_modules/puppeteer/ 
    // .不能少
    mkdir .local-chromium
    cd .local-chromium
    // 818858:%d 根据自己的替换
    mkdir linux-818858
    cd linux-818858
    // 如果上述按照步骤来走,移动文件夹,否则,自行替换路径
    mv ~/node/chrome-linux.zip ~/node/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux.zip
    //解压
    unzip chrome-linux.zip
    
  • 4.安装依赖(不可忽略)

    #依赖库
    sudo yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 nss.x86_64 -y
     
    #字体
    sudo yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
    
  • 5.自测

    cd ~/node
    // 建立文件,此后要跑的js建议都放在这里
    vim test.js
    
    • test.js内容如下

      const puppeteer = require('puppeteer');
      (async () => {
        const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
        const page = await browser.newPage();
        await page.goto('https://www.baidu.com');
        await page.screenshot({path: 'author3q.png'});
        await browser.close();
      })();
      
  • 在该目录下运行:

    node test.js
    //如果目录下有author3q.png,说明一切就绪
    
  • FAQ

    • 手动下载Chrome并解决puppeteer无法使用问题

      https://www.jb51.net/article/150592.htm

      http://jartto.wang/2018/10/13/nodejs-pdf/

    • puppeteer使用截图功能出现乱码

      • 1.安装fontconfig

        yum -y install fontconfig
        //这个命令执行完成之后,就可以在/usr/share文件夹里面看到fonts和fontconfig
        
      • 2.添加中文字体库

        //从window的C:\Windows\Fonts里面把你需要的字体拷贝出来。比如simfang.ttf
        //在CentOS的/usr/share/fonts新建一个叫chinese的文件夹
        //然后把刚刚拷贝字体放到CentOS的/usr/share/fonts/chinese里面
        //修改chinese目录的权限:
         
        mkdir /usr/share/fonts/chinese
        chmod -R 775 /usr/share/fonts/chinese
        
      • 3.接下来需要安装ttmkfdir来搜索目录中所有的字体信息,并汇总生成fonts.scale文件,输入命令

        yum -y install ttmkfdir
        ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
        
      • 4.修改字体配置文件

        vi /etc/fonts/fonts.conf
        
        
         
         /usr/share/fonts
         /usr/share/X11/fonts/Type1
         /usr/share/X11/fonts/TTF
         /usr/local/share/fonts
         添加这行
         /usr/local/share/fonts/chinese
         
         fonts
         
         ~/.fonts
        
      • 5.刷新内存中的字体缓存

        fc-cache
        //看一下现在机器上已经有了刚才添加的字体
        fc-list :lang=zh
        
  • 最终运行文件

    node 1.js path fileName dir

    const puppeteer = require('puppeteer');
    var arguments = process.argv.splice(2);
    console.log('所传递的参数是:', arguments);
    const path = arguments[0] || "";
    const fileName = arguments[1] || "";
    const dir = arguments[2] || "/root/pdf/";
    if (path == "" ) {
      console.log('请传入path:', path);
      return;
    }
    if (fileName == "") {
       console.log('请传入fileName:', fileName);
       return;
    }
     console.log('上传文件目录:', dir);
    (async () => {
      const browser = await puppeteer.launch({
          args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage', 
            '--disable-accelerated-2d-canvas',
            '--disable-gpu'
          ],
          timeout: 50000  //设置超时时间
      });
      const page = await browser.newPage();
      // const url = 'http://10.11.15.1:16868/#/CIAManage/report/detail/'+reportId+'/'+uid;
      const url = path;
      // 防止cpu居高不下,一定要使用try catch 关闭page
      try {
          await page.goto(url, {
              timeout: 30 * 1000,     //超时时间
              waitUntil: 'networkidle0' //无request请求时触发
          });
          console.log('全路径为:', url);
          await page.addStyleTag({
            content: "#cover {display:none}"
          });
          await page.pdf({path: dir + fileName + '.pdf',
              printBackground: true,
              width: '740.725',
              height: '1052.3625',
              '-webkit-print-color-adjust': 'exact',
          });
          await browser.close();
          console.log('导出成功');
    } catch (error) {
        console.log('[REPORTPDF_ERROR_LOG] reportId is [' + reportId + '], error: ', error.message)
        await browser.close();//关闭
      } finally {
        console.log('[REPORTPDF_FINALLY_LOG] reportId is [' + reportId + '] 结束');
      }
    })().catch(error => console.log('[REPORTPDF_ERROR_LOG] reportId is [' + reportId + '], error: ', error.message));
    
    
    
    

    java操作篇

  • yml配置

    scp:
      ip: 192.168.100.128
      port: 22
      username: root
      password: 123456
      url: http://10.11.15.1:16868/#/CIAManage/report/detail
      dir: /root/pdf/
    
  • 控制器

    package com.faner.fast.controller.test;
    
    import com.faner.fast.upms.pojo.bo.FileBO;
    import com.faner.fast.upms.service.FileService;
    import com.faner.fast.util.FileUtil;
    import com.faner.fast.util.ScpClientUtil;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.MediaType;
    import org.springframework.mock.web.MockMultipartFile;
    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.File;
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    import java.util.UUID;
    
    /**
     * description: execController
     * date: 2020/12/2 15:42
     * author: faner
     */
    @Slf4j
    @Validated
    @RestController
    @RequestMapping("/exec")
    @RequiredArgsConstructor
    @Api(value = "exec", tags = "exec")
    public class execController {
    
        private final FileService fileService;
    
        @Value("${scp.ip:127.0.0.1}")
        private String ip;
        @Value("${scp.port:22}")
        private int port;
        @Value("${scp.username:root}")
        private String username;
        @Value("${scp.password:123456}")
        private String password;
        @Value("${scp.url}")
        private String url;
        @Value("${scp.dir:/root/pdf/}")
        private String dir;
        /**
         * 登录远端服务器
         * @return 当前的连接
         * @throws IOException
         */
        @ApiOperation("shell执行")
        @RequestMapping(value = "/pdf",method= {RequestMethod.POST})
        public void  shell() throws IOException {
            String reportId = "37ca8617a73945d7ae8ddad7eddd854e";
            Integer uid = 204;
            String fileName = UUID.randomUUID().toString().replace("-", "");
            File dire = new File(dir);
            if(!dire.exists()){
                dire.mkdirs();
            }
            ScpClientUtil scpClientUtil = ScpClientUtil.getInstance(ip, port, username, password);
            String script = "node /root/node/test3.js "+ url +"/"+reportId+"/"+uid+ " " +fileName + " " + dir;
            ScpClientUtil.ShellResult exec = scpClientUtil.exec(script, StandardCharsets.UTF_8);
            log.info(">>>>>>Result>>>>>>>");
            log.info(exec.getResult());
            log.info(">>>>>>ErrorMsg>>>>>>>>");
            log.info(exec.getErrorMsg());
            String name =dir+fileName+".pdf";
            //校验文件是否存在
    
            boolean exists = FileUtil.exists(name);
            if (exists){
                MultiValueMap o1 = new LinkedMultiValueMap();
                //上传oss
                MultipartFile file = new MockMultipartFile(name,name, MediaType.MULTIPART_FORM_DATA_VALUE, FileUtil.getByte(new File(name)));
                o1.add("file",file);
                List upload = fileService.upload(o1);
                //删除文件
                FileUtil.deleteFile(name);
                //发送邮件发送链接删除后操作即可 发送文件需要在删除前操作 比较耗费服务器资源 建议发送链接
            }
        }
    }
    
    
  • linux操作工具类

    
            
                ch.ethz.ganymed
                ganymed-ssh2
                build210
            
    
package com.faner.fast.util;

import ch.ethz.ssh2.*;
import com.faner.fast.exception.FailedException;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 远程执行linux命令
 * description: ExecUtil
 * date: 2020/12/2 16:44
 * author: faner
 */
@Slf4j
public class ScpClientUtil {
    /** 超时时间 */
    private static final int TIME_OUT = 1000 * 5 * 60;

    static private Map instance = Maps.newHashMap();

    static synchronized public ScpClientUtil getInstance(String ip, int port, String username, String password) {
        if (instance.get(ip) == null) {
            instance.put(ip, new ScpClientUtil(ip, port, username, password));
        }
        return instance.get(ip);
    }

    public ScpClientUtil(String ip, int port, String username, String password) {
        this.ip = ip;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 执行一个命令
     * @param scripts  需要执行的脚本
     * @param charset  字符编码
     * @return ShellResult类
     * @throws Exception
     */
    public ShellResult exec( String scripts, Charset charset) throws IOException {

        Connection conn = new Connection(ip, port);

        try {
            conn.connect();
            // Open a new {@link Session} on this connection
            boolean isAuthenticated = conn.authenticateWithPassword(username, password);
            if (!isAuthenticated) {
                log.error("authentication failed");
                throw new FailedException("authentication failed");
            }
            Session session = conn.openSession();
            InputStream stdOut = new StreamGobbler(session.getStdout()); InputStream stdErr = new StreamGobbler(session.getStderr());
            session.execCommand(scripts);
            String outStr = processStream(stdOut, charset.name());
            String outErr = processStream(stdErr, charset.name());
            session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
            int exitStatus = session.getExitStatus();
            return new ShellResult(outStr, outErr, exitStatus);
        }finally{
            conn.close();
        }
    }

    /**
     * 执行脚本
     * @param in      输入流
     * @param charset 字符编码
     * @return
     * @throws IOException
     */
    private static String processStream(InputStream in, String charset) throws IOException {
        byte[] buf = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while (in.read(buf) != -1) {
            sb.append(new String(buf, charset));
        }
        return sb.toString();
    }

    public void getFile(String remoteFile, String localTargetDirectory) {
        Connection conn = new Connection(ip, port);
        try {
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(username, password);
            if (!isAuthenticated) {
                System.err.println("authentication failed");
            }
            SCPClient client = new SCPClient(conn);
            client.get(remoteFile, localTargetDirectory);
        } catch (IOException ex) {
            Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
        }finally{
            conn.close();
        }
    }

    public void putFile(String localFile, String remoteTargetDirectory) {
        putFile(localFile, null, remoteTargetDirectory);
    }

    public void putFile(String localFile, String remoteFileName, String remoteTargetDirectory) {
        putFile(localFile, remoteFileName, remoteTargetDirectory,null);
    }

    public void putFile(String localFile, String remoteFileName, String remoteTargetDirectory, String mode) {
        Connection conn = new Connection(ip, port);
        try {
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(username, password);
            if (!isAuthenticated) {
                System.err.println("authentication failed");
            }
            SCPClient client = new SCPClient(conn);
            if ((mode == null) || (mode.length() == 0)) {
                mode = "0600";
            }
            if (remoteFileName == null) {
                client.put(localFile, remoteTargetDirectory);
            } else {
                client.put(localFile, remoteFileName, remoteTargetDirectory, mode);
            }
        } catch (IOException ex) {
            Logger.getLogger(ScpClientUtil.class.getName()).log(Level.SEVERE, null, ex);
        }finally{
            conn.close();
        }
    }

    private String ip;
    private int port;
    private String username;
    private String password;


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public  class ShellResult  {

        /** 脚本输出结果 */
        private String result;
        /** 异常输出结果 */
        private String errorMsg;
        /** 回话退出状态 */
        private int exitStatus;

        /** 是否成功关闭会话 */
        public boolean getSuccess() {
            return this.exitStatus == 0;
        }
    }
}

  • 文件工具类

    
    
    commons-io
    commons-io
    2.4
    
    
package com.faner.fast.util;

import cn.hutool.core.util.IdUtil;
import com.faner.fast.exception.FileTooLargeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * description: FileUtil
 * date: 2020/11/26 15:19
 * author: faner
 */
@Slf4j
public class FileUtil {

    /**
     * 系统临时目录
     * 
* windows 包含路径分割符,但Linux 不包含, * 在windows \\==\ 前提下, * 为安全起见 同意拼装 路径分割符, *
     *       java.io.tmpdir
     *       windows : C:\Users/xxx\AppData\Local\Temp\
     *       linux: /temp
     * 
*/ public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator; /** * 定义GB的计算常量 */ private static final int GB = 1024 * 1024 * 1024; /** * 定义MB的计算常量 */ private static final int MB = 1024 * 1024; /** * 定义KB的计算常量 */ private static final int KB = 1024; /** * 格式化小数 */ private static final DecimalFormat DF = new DecimalFormat("0.00"); public static final String IMAGE = "图片"; public static final String TXT = "文档"; public static final String MUSIC = "音乐"; public static final String VIDEO = "视频"; public static final String OTHER = "其他"; private static List filePathList = new ArrayList(); /** * MultipartFile转File */ public static File toFile(MultipartFile multipartFile) { // 获取文件名 String fileName = multipartFile.getOriginalFilename(); // 获取文件后缀 String prefix = "." + getExtensionName(fileName); File file = null; try { // 用uuid作为文件名,防止生成的临时文件重复 file = File.createTempFile(IdUtil.simpleUUID(), prefix); // MultipartFile to File multipartFile.transferTo(file); } catch (IOException e) { log.error(e.getMessage(), e); } return file; } /** * 获取文件扩展名,不带 . */ public static String getExtensionName(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length() - 1))) { return filename.substring(dot + 1); } } return filename; } /** * Java文件操作 获取不带扩展名的文件名 */ public static String getFileNameNoEx(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length()))) { return filename.substring(0, dot); } } return filename; } /** * 文件大小转换 */ public static String getSize(long size) { String resultSize; if (size / GB >= 1) { //如果当前Byte的值大于等于1GB resultSize = DF.format(size / (float) GB) + "GB "; } else if (size / MB >= 1) { //如果当前Byte的值大于等于1MB resultSize = DF.format(size / (float) MB) + "MB "; } else if (size / KB >= 1) { //如果当前Byte的值大于等于1KB resultSize = DF.format(size / (float) KB) + "KB "; } else { resultSize = size + "B "; } return resultSize; } /** * inputStream 转 File */ static File inputStreamToFile(InputStream ins, String name) throws Exception { File file = new File(SYS_TEM_DIR + name); if (file.exists()) { return file; } OutputStream os = new FileOutputStream(file); int bytesRead; int len = 8192; byte[] buffer = new byte[len]; while ((bytesRead = ins.read(buffer, 0, len)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); return file; } /** * 将文件名解析成文件的上传路径 */ public static File upload(MultipartFile file, String filePath) { Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); String name = getFileNameNoEx(file.getOriginalFilename()); String suffix = getExtensionName(file.getOriginalFilename()); String nowStr = "-" + format.format(date); try { String fileName = name + nowStr + "." + suffix; String path = filePath + fileName; // getCanonicalFile 可解析正确各种路径 File dest = new File(path).getCanonicalFile(); // 检测是否存在目录 if (!dest.getParentFile().exists()) { if (!dest.getParentFile().mkdirs()) { System.out.println("was not successful."); } } // 文件写入 file.transferTo(dest); return dest; } catch (Exception e) { log.error(e.getMessage(), e); } return null; } public static String getFileType(String type) { String documents = "txt doc pdf ppt pps xlsx xls docx"; String music = "mp3 wav wma mpa ram ra aac aif m4a"; String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; if (image.contains(type)) { return IMAGE; } else if (documents.contains(type)) { return TXT; } else if (music.contains(type)) { return MUSIC; } else if (video.contains(type)) { return VIDEO; } else { return OTHER; } } public static void checkSize(long maxSize, long size) { // 1M int len = 1024 * 1024; if (size > (maxSize * len)) { throw new FileTooLargeException("文件超出规定大小"); } } /** * 判断两个文件是否相同 */ public static boolean check(File file1, File file2) { String img1Md5 = getMd5(file1); String img2Md5 = getMd5(file2); return img1Md5.equals(img2Md5); } /** * 判断两个文件是否相同 */ public static boolean check(String file1Md5, String file2Md5) { return file1Md5.equals(file2Md5); } /** * 将文件转换成byte数组 * @param file * @return byte[] */ public static byte[] getByte(File file) { // 得到文件长度 byte[] b = new byte[(int) file.length()]; try { InputStream in = new FileInputStream(file); try { System.out.println(in.read(b)); } catch (IOException e) { log.error(e.getMessage(), e); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } catch (FileNotFoundException e) { log.error(e.getMessage(), e); return null; } return b; } /** * 获取文件md5值 */ public static String getMd5(File file) { return getMd5(getByte(file)); } public static String getMd5(byte[] bytes) { // 16进制字符 char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; try { MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(bytes); byte[] md = mdTemp.digest(); int j = md.length; char[] str = new char[j * 2]; int k = 0; // 移位 输出字符串 for (byte byte0 : md) { str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { log.error(e.getMessage(), e); } return null; } /** * 判断文件是否存在 * @param filePath * @return */ public static boolean exists(String filePath) { boolean exists = false; File file = new File(filePath); if (file.exists()) { exists = true; } return exists; } /** * 删除指定文件夹 * * @param filePath */ public static void deleteDirectory(String filePath) { FileUtils.deleteQuietly(new File(filePath)); } /** * 删除指定文件 * @param filePath */ public static void deleteFile(String filePath) { try { FileUtils.forceDelete(new File(filePath)); } catch (IOException e) { e.printStackTrace(); } } /** * 查找指定路径下指定后缀的所有文件(非递归查找) * * @param filePath 文件目录 * @param extensionName 文件扩展名 */ public static List getFileUnderFolder(String filePath, String extensionName) { List filPathList = new ArrayList(); File file = new File(filePath); File[] fileList = file.listFiles(); for (File f : fileList) { if (f.isFile() && f.getName().endsWith(extensionName)) { filPathList.add(f.getAbsolutePath()); } } return filPathList; } /** * 查找指定路径下指定后缀的所有文件(递归查找) * * @param filePath 文件目录 * @param extensionName 文件扩展名 */ public static List getFileUnderFolderCursively(String filePath, String extensionName) { File file = new File(filePath); File[] fileList = file.listFiles(); for (File f : fileList) { if (f.isFile() && f.getName().endsWith(extensionName)) { filePathList.add(f.getAbsolutePath()); } else if (f.isDirectory()) { getFileUnderFolderCursively(f.getAbsolutePath(), extensionName); } } return filePathList; } /** * 递归复制指定路径下指定后缀的所有文件到指定目录 * * @param filePath * @param extensionName */ public static void copyFilesUnderFolderCursively(String filePath, String extensionName, String dstPath) { File file = new File(filePath); File[] fileList = file.listFiles(); for (File f : fileList) { if (f.isFile() && f.getName().endsWith(extensionName)) { try { FileUtils.copyFileToDirectory(f, new File(dstPath)); } catch (IOException e) { e.printStackTrace(); } } else if (f.isDirectory()) { copyFilesUnderFolderCursively(f.getAbsolutePath(), extensionName, dstPath); } } } /** * 读取文件内容 * @param filePath * @param charsetName 编码格式 * @return */ public static String readFileContent(String filePath, String charsetName) { String content = ""; File file = new File(filePath); if (file.exists()) { Long fileLength = file.length(); byte[] fileContent = new byte[fileLength.intValue()]; try { FileInputStream in = new FileInputStream(file); in.read(fileContent); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { content = new String(fileContent, charsetName); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return content; } /** * 读取文件内容 */ public static ArrayList readFileContentByLine(String filePath, String charsetName) { ArrayList list = new ArrayList(); String str = ""; FileInputStream fis = null; InputStreamReader isr = null; BufferedReader br = null; // 用于包装InputStreamReader,提高处理性能,因为BufferedReader有缓冲,InputStreamReader则没有 try { fis = new FileInputStream(filePath); // FileInputStream // 从文件系统中的某个文件中获取字节 isr = new InputStreamReader(fis, charsetName);// InputStreamReader是字节流通往字符流的桥梁 br = new BufferedReader(isr);// 从字符输入流中读取文件中的内容,封装了一个new while ((str = br.readLine()) != null) { list.add(str); } } catch (FileNotFoundException e) { System.out.println("找不到指定文件"); } catch (IOException e) { System.out.println("读取文件失败"); } finally { try { br.close(); isr.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } } return list; } /** * 下载文件 * * @param request / * @param response / * @param file / */ public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { response.setCharacterEncoding(request.getCharacterEncoding()); response.setContentType("application/octet-stream"); FileInputStream fis = null; try { fis = new FileInputStream(file); response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); IOUtils.copy(fis, response.getOutputStream()); response.flushBuffer(); } catch (Exception e) { log.error(e.getMessage(), e); } finally { if (fis != null) { try { fis.close(); if (deleteOnExit) { file.deleteOnExit(); } } catch (IOException e) { log.error(e.getMessage(), e); } } } } }

你可能感兴趣的:(Linux 机器安装nodejs 、puppeteer及踩坑(页面抓取转pdf))