Linux 機(jī)器安裝nodejs 衷戈、puppeteer及踩坑(頁(yè)面抓取轉(zhuǎn)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.移動(dòng)文件夾 將文件夾移動(dòng)到用戶目錄下再扭,并重命名為node(通常該步驟是便于應(yīng)用程序使用)

    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.添加環(huán)境變量 和上步略有重復(fù)食绿,不過(guò)建議加上

    sudo vi /etc/profile; 
    //特別提醒:如果前文移動(dòng)目錄自定義梳凛,這里也要同步修改
    export NODE_HOME=~/node/bin
    export PATH=$NODE_HOME:$PATH
     
    
  • 6.自測(cè)

    node -v
    //打印版本號(hào)說(shuō)明安裝成功
    

puppeteer安裝

node對(duì)于路徑很看重锨苏,因此把模塊安裝在哪個(gè)目錄下很關(guān)鍵疙教,否則你的js文件可能因?yàn)槿鄙倌K而不能運(yùn)行

如果完成上述node安裝,你的node所在路徑應(yīng)該是/node伞租,之后的包安裝都在/node下進(jìn)行

  • 1.安裝

    //確保進(jìn)入node文件夾下
    cd ~/node 
    //安裝puppeteer,不下載chrome
    npm install puppeteer --ignore-scripts --save
    
  • 2.獲取chrome

    • 查看所需chrome版本號(hào):版本號(hào)可以在node_modules/puppeteer/package.jsonpuppeteer.chromium_revision獲得贞谓,現(xiàn)在是818858,根據(jù)puppeteer需要自行替換葵诈,后續(xù)用%d代替(必須裸弦,否則puppeteer特性可能不支持)|版本中也許不存在版本信息,先下載上作喘,自測(cè)中會(huì)提示需要的版本
    wget -c 'https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/818858/chrome-linux.zip'
    

已經(jīng)下載好 鏈接:https://pan.baidu.com/s/1c0pKDeqCmt0UIFAf6TncDA
提取碼:gs26

  • 3.將chrome放在指定目錄下

    cd node_modules/puppeteer/ 
    // .不能少
    mkdir .local-chromium
    cd .local-chromium
    // 818858:%d 根據(jù)自己的替換
    mkdir linux-818858
    cd linux-818858
    // 如果上述按照步驟來(lái)走理疙,移動(dòng)文件夾,否則泞坦,自行替換路徑
    mv ~/node/chrome-linux.zip ~/node/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux.zip
    //解壓
    unzip chrome-linux.zip
    
  • 4.安裝依賴(不可忽略)

    #依賴庫(kù)
    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.自測(cè)

    cd ~/node
    // 建立文件,此后要跑的js建議都放在這里
    vim test.js
    
    • test.js內(nèi)容如下

      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();
      })();
      
  • 在該目錄下運(yùn)行:

    node test.js
    //如果目錄下有author3q.png窖贤,說(shuō)明一切就緒
    
  • FAQ

    • 手動(dòng)下載Chrome并解決puppeteer無(wú)法使用問(wèn)題

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

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

    • puppeteer使用截圖功能出現(xiàn)亂碼

      • 1.安裝fontconfig

        yum -y install fontconfig
        //這個(gè)命令執(zhí)行完成之后,就可以在/usr/share文件夾里面看到fonts和fontconfig
        
      • 2.添加中文字體庫(kù)

        //從window的C:\Windows\Fonts里面把你需要的字體拷貝出來(lái)。比如simfang.ttf
        //在CentOS的/usr/share/fonts新建一個(gè)叫chinese的文件夾
        //然后把剛剛拷貝字體放到CentOS的/usr/share/fonts/chinese里面
        //修改chinese目錄的權(quán)限:
         
        mkdir /usr/share/fonts/chinese
        chmod -R 775 /usr/share/fonts/chinese
        
      • 3.接下來(lái)需要安裝ttmkfdir來(lái)搜索目錄中所有的字體信息赃梧,并匯總生成fonts.scale文件滤蝠,輸入命令

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

        vi /etc/fonts/fonts.conf
        
        <!-- Font directory list -->
         
         <dir>/usr/share/fonts</dir>
         <dir>/usr/share/X11/fonts/Type1</dir>
         <dir>/usr/share/X11/fonts/TTF</dir>
         <dir>/usr/local/share/fonts</dir>
         添加這行
         <dir>/usr/local/share/fonts/chinese</dir>
         
         <dir prefix="xdg">fonts</dir>
         <!-- the following element will be removed in the future -->
         <dir>~/.fonts</dir>
        
      • 5.刷新內(nèi)存中的字體緩存

        fc-cache
        //看一下現(xiàn)在機(jī)器上已經(jīng)有了剛才添加的字體
        fc-list :lang=zh
        
  • 最終運(yùn)行文件

    node 1.js path fileName dir

    const puppeteer = require('puppeteer');
    var arguments = process.argv.splice(2);
    console.log('所傳遞的參數(shù)是:', arguments);
    const path = arguments[0] || "";
    const fileName = arguments[1] || "";
    const dir = arguments[2] || "/root/pdf/";
    if (path == "" ) {
      console.log('請(qǐng)傳入path:', path);
      return;
    }
    if (fileName == "") {
       console.log('請(qǐng)傳入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  //設(shè)置超時(shí)時(shí)間
      });
      const page = await browser.newPage();
      // const url = 'http://10.11.15.1:16868/#/CIAManage/report/detail/'+reportId+'/'+uid;
      const url = path;
      // 防止cpu居高不下,一定要使用try catch 關(guān)閉page
      try {
          await page.goto(url, {
              timeout: 30 * 1000,     //超時(shí)時(shí)間
              waitUntil: 'networkidle0' //無(wú)request請(qǐng)求時(shí)觸發(fā)
          });
          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('導(dǎo)出成功');
    } catch (error) {
        console.log('[REPORTPDF_ERROR_LOG] reportId is [' + reportId + '], error: ', error.message)
        await browser.close();//關(guān)閉
      } finally {
        console.log('[REPORTPDF_FINALLY_LOG] reportId is [' + reportId + '] 結(jié)束');
      }
    })().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;
        /**
         * 登錄遠(yuǎn)端服務(wù)器
         * @return 當(dāng)前的連接
         * @throws IOException
         */
        @ApiOperation("shell執(zhí)行")
        @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";
            //校驗(yàn)文件是否存在
    
            boolean exists = FileUtil.exists(name);
            if (exists){
                MultiValueMap<String, MultipartFile> o1 = new LinkedMultiValueMap<String, MultipartFile>();
                //上傳oss
                MultipartFile file = new MockMultipartFile(name,name, MediaType.MULTIPART_FORM_DATA_VALUE, FileUtil.getByte(new File(name)));
                o1.add("file",file);
                List<FileBO> upload = fileService.upload(o1);
                //刪除文件
                FileUtil.deleteFile(name);
                //發(fā)送郵件發(fā)送鏈接刪除后操作即可 發(fā)送文件需要在刪除前操作 比較耗費(fèi)服務(wù)器資源 建議發(fā)送鏈接
            }
        }
    }
    
    
  • linux操作工具類

    <!-- shell       -->
            <dependency>
                <groupId>ch.ethz.ganymed</groupId>
                <artifactId>ganymed-ssh2</artifactId>
                <version>build210</version>
            </dependency>
    
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;

/**
 * 遠(yuǎn)程執(zhí)行l(wèi)inux命令
 * description: ExecUtil
 * date: 2020/12/2 16:44
 * author: faner
 */
@Slf4j
public class ScpClientUtil {
    /** 超時(shí)時(shí)間 */
    private static final int TIME_OUT = 1000 * 5 * 60;

    static private Map<String,ScpClientUtil> 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;
    }

    /**
     * 執(zhí)行一個(gè)命令
     * @param scripts  需要執(zhí)行的腳本
     * @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();
        }
    }

    /**
     * 執(zhí)行腳本
     * @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  {

        /** 腳本輸出結(jié)果 */
        private String result;
        /** 異常輸出結(jié)果 */
        private String errorMsg;
        /** 回話退出狀態(tài) */
        private int exitStatus;

        /** 是否成功關(guān)閉會(huì)話 */
        public boolean getSuccess() {
            return this.exitStatus == 0;
        }
    }
}

  • 文件工具類

    <!-- io       -->
    <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
    </dependency>
    
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 {

    /**
     * 系統(tǒng)臨時(shí)目錄
     * <br>
     * windows 包含路徑分割符授嘀,但Linux 不包含,
     * 在windows \\==\ 前提下物咳,
     * 為安全起見(jiàn) 同意拼裝 路徑分割符,
     * <pre>
     *       java.io.tmpdir
     *       windows : C:\Users/xxx\AppData\Local\Temp\
     *       linux: /temp
     * </pre>
     */
    public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
    /**
     * 定義GB的計(jì)算常量
     */
    private static final int GB = 1024 * 1024 * 1024;
    /**
     * 定義MB的計(jì)算常量
     */
    private static final int MB = 1024 * 1024;
    /**
     * 定義KB的計(jì)算常量
     */
    private static final int KB = 1024;

    /**
     * 格式化小數(shù)
     */
    private static final DecimalFormat DF = new DecimalFormat("0.00");

    public static final String IMAGE = "圖片";
    public static final String TXT = "文檔";
    public static final String MUSIC = "音樂(lè)";
    public static final String VIDEO = "視頻";
    public static final String OTHER = "其他";

    private static List<String> filePathList = new ArrayList<String>();
    /**
     * MultipartFile轉(zhuǎn)File
     */
    public static File toFile(MultipartFile multipartFile) {
        // 獲取文件名
        String fileName = multipartFile.getOriginalFilename();
        // 獲取文件后綴
        String prefix = "." + getExtensionName(fileName);
        File file = null;
        try {
            // 用uuid作為文件名蹄皱,防止生成的臨時(shí)文件重復(fù)
            file = File.createTempFile(IdUtil.simpleUUID(), prefix);
            // MultipartFile to File
            multipartFile.transferTo(file);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return file;
    }

    /**
     * 獲取文件擴(kuò)展名览闰,不帶 .
     */
    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文件操作 獲取不帶擴(kuò)展名的文件名
     */
    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;
    }

    /**
     * 文件大小轉(zhuǎn)換
     */
    public static String getSize(long size) {
        String resultSize;
        if (size / GB >= 1) {
            //如果當(dāng)前Byte的值大于等于1GB
            resultSize = DF.format(size / (float) GB) + "GB   ";
        } else if (size / MB >= 1) {
            //如果當(dāng)前Byte的值大于等于1MB
            resultSize = DF.format(size / (float) MB) + "MB   ";
        } else if (size / KB >= 1) {
            //如果當(dāng)前Byte的值大于等于1KB
            resultSize = DF.format(size / (float) KB) + "KB   ";
        } else {
            resultSize = size + "B   ";
        }
        return resultSize;
    }

    /**
     * inputStream 轉(zhuǎn) 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();
            // 檢測(cè)是否存在目錄
            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("文件超出規(guī)定大小");
        }
    }

    /**
     * 判斷兩個(gè)文件是否相同
     */
    public static boolean check(File file1, File file2) {
        String img1Md5 = getMd5(file1);
        String img2Md5 = getMd5(file2);
        return img1Md5.equals(img2Md5);
    }

    /**
     * 判斷兩個(gè)文件是否相同
     */
    public static boolean check(String file1Md5, String file2Md5) {
        return file1Md5.equals(file2Md5);
    }

    /**
     * 將文件轉(zhuǎn)換成byte數(shù)組
     * @param file
     * @return byte[]
     */
    public static byte[] getByte(File file) {
        // 得到文件長(zhǎng)度
        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進(jìn)制字符
        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 文件擴(kuò)展名
     */
    public static List<String> getFileUnderFolder(String filePath, String extensionName) {
        List<String> filPathList = new ArrayList<String>();
        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 文件擴(kuò)展名
     */
    public static List<String> 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;
    }

    /**
     * 遞歸復(fù)制指定路徑下指定后綴的所有文件到指定目錄
     *
     * @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);
            }
        }
    }

    /**
     * 讀取文件內(nèi)容
     * @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;
    }

    /**
     * 讀取文件內(nèi)容
     */
    public static ArrayList<String> readFileContentByLine(String filePath, String charsetName) {
        ArrayList<String> list = new ArrayList<String>();
        String str = "";
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null; // 用于包裝InputStreamReader,提高處理性能,因?yàn)锽ufferedReader有緩沖巷折,InputStreamReader則沒(méi)有

        try {
            fis = new FileInputStream(filePath); // FileInputStream
            // 從文件系統(tǒng)中的某個(gè)文件中獲取字節(jié)
            isr = new InputStreamReader(fis, charsetName);// InputStreamReader是字節(jié)流通往字符流的橋梁
            br = new BufferedReader(isr);// 從字符輸入流中讀取文件中的內(nèi)容压鉴,封裝了一個(gè)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);
                }
            }
        }
    }


}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盔几,隨后出現(xiàn)的幾起案子晴弃,更是在濱河造成了極大的恐慌,老刑警劉巖逊拍,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件上鞠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡芯丧,警方通過(guò)查閱死者的電腦和手機(jī)芍阎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缨恒,“玉大人谴咸,你說(shuō)我怎么就攤上這事∑叮” “怎么了岭佳?”我有些...
    開(kāi)封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萧锉。 經(jīng)常有香客問(wèn)我珊随,道長(zhǎng),這世上最難降的妖魔是什么柿隙? 我笑而不...
    開(kāi)封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任叶洞,我火速辦了婚禮,結(jié)果婚禮上禀崖,老公的妹妹穿的比我還像新娘衩辟。我一直安慰自己,他們只是感情好波附,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布艺晴。 她就那樣靜靜地躺著昼钻,像睡著了一般价淌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上久锥,一...
    開(kāi)封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天新博,我揣著相機(jī)與錄音,去河邊找鬼闯两。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谦炒。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼风喇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宁改!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起魂莫,我...
    開(kāi)封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤还蹲,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后耙考,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谜喊,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年倦始,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斗遏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鞋邑,死狀恐怖诵次,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枚碗,我是刑警寧澤逾一,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站肮雨,受9級(jí)特大地震影響遵堵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酷含,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一鄙早、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧椅亚,春花似錦限番、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扩灯。三九已至,卻和暖如春霜瘪,著一層夾襖步出監(jiān)牢的瞬間珠插,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工颖对, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捻撑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓缤底,卻偏偏與公主長(zhǎng)得像顾患,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子个唧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容