目录列表生成PDF预览图脚本

当一个目录下有100多套图包时,很难找某一个图包,只能看名字或者全部搜出来翻页找,容易眼花缭乱。有了这个脚本之后,也方便了后续的按需下载。

实现思路:根据填入路径,获取路径下的全部目录,每个目录取一张图片,把目录名和图片写入到PDF文件。

生成结果:会在输入目录下,生成一个`output.pdf`文件,内容如下。

图片[1]-目录列表生成PDF预览图脚本-死宅屋
图片[2]-目录列表生成PDF预览图脚本-死宅屋

下载:

执行脚本在下面链接里,需要把里面的`NotoSerifHK-VariableFont_wght.ttf`字体复制到C盘根目录下,否则没用。

https://pan.baidu.com/s/1prKMt3dhdu4IvyhzwLsZOA?pwd=iszw

2024-4-3 01:24:30:修复exe程序放桌面时,无法执行的问题

golang代码:

package main

/**
*	生成目录PDF文件
 */
import (
	"bufio"
	"fmt"
	mapset "github.com/deckarep/golang-set"
	"github.com/disintegration/imaging"
	"github.com/google/uuid"
	"github.com/signintech/gopdf"
	"image"
	"image/jpeg"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
)

var scanRootPath = "" // 搜索的要格式化的目录
var ttfpath = "C:\\NotoSerifHK-VariableFont_wght.ttf"

var photoExt = []interface{}{
	".png",
	".jpg",
	".jpe",
	".jpg2",
	".jpeg",
	".gif",
	".bmp",
	".dif",
	".wmf",
	".svg",
	".ico",
	".tif",
	".tiff",
	".webp",
	".heic",
	".jfif",
}
var videoExt = []interface{}{
	".mp4",
	".mpg",
	".mpe",
	".mpeg",
	".qt",
	".mov",
	".m4v",
	".wmv",
	".avi",
	".webm",
	".flv",
	".mkv",
	".ts",
}
var audioExt = []interface{}{
	".mp3",
	".mid",
	".midi",
	".wav",
	".m3u",
	".m4a",
	".ogg",
	".ra",
}

// 保存全部路径
var scanPathList []string

// 判断文件夹或文件是否存在
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

// 获取目录大小
func GetDirSize(path string) string {
	var size int64
	err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			size += info.Size()
		}
		return err
	})
	if err != nil {
		panic("获取文件信息失败")
	}
	return ByteCountBinary(size)
}

// 字节转人类可读
func ByteCountDecimal(b int64) string {
	const unit = 1000
	if b < unit {
		return fmt.Sprintf("%d B", b)
	}
	div, exp := int64(unit), 0
	for n := b / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
}

// 字节转人类可读
func ByteCountBinary(b int64) string {
	const unit = 1024
	if b < unit {
		return fmt.Sprintf("%dB", b)
	}
	div, exp := int64(unit), 0
	for n := b / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.2f%cB", float64(b)/float64(div), "KMGTPE"[exp])
}

func GenThumbnail(img_path string) string {
	// 打开图片文件
	file, err := os.Open(img_path)
	if err != nil {
		fmt.Println("无法打开图片文件:", err)
		panic(err)
	}
	defer file.Close()

	// 解码图片文件
	img, _, err := image.Decode(file)
	if err != nil {
		fmt.Println("解码图片失败:", err)
		panic(err)
	}

	// 生成缩略图
	thumbnail := imaging.Thumbnail(img, int(gopdf.PageSizeA4.W), int(gopdf.PageSizeA4.H), imaging.Lanczos)

	if PathExist, _ := PathExists(fmt.Sprintf("%s/.build_index_tmp", scanRootPath)); PathExist == false {
		err = os.MkdirAll(fmt.Sprintf("%s/.build_index_tmp", scanRootPath), os.ModePerm)
	}

	// 创建输出文件
	outputPath := fmt.Sprintf("%s/.build_index_tmp/_%s.jpg", scanRootPath, uuid.New().String())
	outputFile, err := os.Create(outputPath)
	if err != nil {
		fmt.Println("无法创建输出文件:", err)
		panic(err)
	}
	defer outputFile.Close()

	// 将缩略图保存为JPEG格式
	err = jpeg.Encode(outputFile, thumbnail, nil)
	if err != nil {
		fmt.Println("保存缩略图失败:", err)
		panic(err)
	}

	return outputPath
}

func ReplacePath(sourcePathname string, pdf *gopdf.GoPdf) {
	// 开始扫描此目录下的全部文件
	sourcePathname = strings.ReplaceAll(sourcePathname, "\\", "/")
	lastname := path.Base(sourcePathname)
	var err error

	useFile := false
	err = filepath.Walk(sourcePathname, func(pathstr string, info os.FileInfo, err error) error {
		if info.IsDir() == false && useFile == false {
			ext := strings.ToLower(path.Ext(info.Name()))
			switch {
			case mapset.NewSetFromSlice(photoExt).Contains(ext):
				// 添加文本
				pdf.AddPage()
				// 读取图像文件
				imageFile := GenThumbnail(pathstr)
				pdf.SetFillColor(255, 252, 255)
				pdf.SetStrokeColor(255, 255, 255)
				err = pdf.Image(imageFile, 0, 0, &gopdf.Rect{W: gopdf.PageSizeA4.W, H: gopdf.PageSizeA4.H})
				if err != nil {
					//panic(err)
					log.Println("写入图片到PDF错误", err.Error())
					return nil
				}
				pdf.RectFromUpperLeftWithStyle(0, 0, gopdf.PageSizeA4.W, 40, "FD") // "FD" 表示填充并描边
				pdf.SetTextColor(0, 0, 0)
				err = pdf.Cell(&gopdf.Rect{
					W: gopdf.PageSizeA4.W,
					H: 40,
				}, lastname)
				if err != nil {
					log.Println("写入文本到PDF错误", err.Error())
					return nil
				}
				useFile = true
			case mapset.NewSetFromSlice(videoExt).Contains(ext):

			case mapset.NewSetFromSlice(audioExt).Contains(ext):

			default:
			}
		}
		return err
	})
	if err != nil {
		log.Println("扫描文件列表错误", err.Error())
		return
	}
}
func GetAllDirs(pathname string, s []string) ([]string, error) {
	rd, err := ioutil.ReadDir(pathname)
	if err != nil {
		fmt.Println("read dir fail:", err)
		return s, err
	}
	for _, fi := range rd {
		if fi.IsDir() {
			fullName := pathname + "\\" + fi.Name()
			s = append(s, fullName)
		}
	}
	return s, nil
}
func haveError() {
	log.Println("结束:可 CTRL+C 或者 关闭窗口")
	sigChan := make(chan os.Signal)
	signal.Notify(sigChan)
	<-sigChan
}

func main() {

	fmt.Println("———— 根据输入路径下的目录,生成预览PDF (CTRL+C可随时终止)")
	fmt.Println("———— 注意:请勿直接输入盘符根目录。")

	fmt.Println("请粘贴要执行的目录地址(回车后执行):")
	reader := bufio.NewReader(os.Stdin)       // 标准输入输出
	scanRootPath, _ = reader.ReadString('\n') // 回车结束
	scanRootPath = strings.TrimSpace(scanRootPath)

	scanRootPath = strings.Trim(scanRootPath, " ")
	if scanRootPath == "" {
		log.Println("错误:没有获取到你输入的目录")
		haveError()
	}

	// 判断扫描的目录是否存在
	if PathExist, _ := PathExists(scanRootPath); PathExist == false {
		log.Println("扫描的目录不存在", scanRootPath)
		return
	}
	var err error

	// 创建一个PDF文档
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{
		PageSize: *gopdf.PageSizeA4,
	}) // A4尺寸

	// 加载 Arial 字体文件
	err = pdf.AddTTFFont("NotoSerifHK-VariableFont_wght", ttfpath)
	if err != nil {
		panic(err)
	}

	// 设置字体
	err = pdf.SetFont("NotoSerifHK-VariableFont_wght", "", 18)
	if err != nil {
		panic(err)
	}

	//获取当前目录下的所有目录信息
	scanPathList, err = GetAllDirs(scanRootPath, scanPathList)
	if err != nil {
		log.Println("读取当前目录出错", err.Error())
		return
	}
	// 处理目录
	for i, _ := range scanPathList {
		loopPath := scanPathList[i]
		ReplacePath(loopPath, &pdf)
	}

	// 保存PDF文件
	err = pdf.WritePdf(fmt.Sprintf("%s/%s", scanRootPath, "output.pdf"))
	if err != nil {
		//panic(err)
		log.Println("保存PDF文件出错", err.Error())
	}
	os.RemoveAll(fmt.Sprintf("%s/.build_index_tmp", scanRootPath))
	haveError()
}
温馨提示:本文最后更新于2024-04-03 01:24:50,某些文章具有时效性,若有错误或已失效,请在下方留言或者右下角私信。
注意:为了节省大家的时间,不会使用百度云下载也不愿意看解压说明教程、或者遇到不会解压的问题也不右下角私聊站长解决就直接投诉订单的朋友,还是别开通会员了,既浪费了您的时间也浪费了您的精力,感谢理解。解压说明
© 版权声明
THE END
喜欢就支持一下吧
点赞4
留言 共2条

请登录后发表评论

    请登录后查看评论内容