php+wkhtmltoimage 将html转成图片 PHP

1.安装wkhtmltopdf
ubuntu 安装
sudo apt-get install wkhtmltopdf
centos 安装
sudo yum install wkhtmltopdf

2.php中使用thinkphp-template模板组件

$res = ThinkPHP::render('mobile',['html'=>$html]);

        $filename = runtime_path().'/html/'.time().mt_rand(1,999).'.html';
        file_put_contents($filename, $res);

        $tempHtmlFile = $filename;

        // 生成图像输出文件路径
        $outputImageFile = runtime_path().'/html/res.png';

        // 使用 wkhtmltoimage 命令行工具生成图像
        //quality 质量 1-100
        //width 宽度
        //-disable-smart-width 禁用宽度自动调整
        // --zoom 0.8 缩小分辨率
        $command = "wkhtmltoimage --width 700 --quality 75 --disable-smart-width $tempHtmlFile $outputImageFile";
        //exec($command);
        exec($command, $output, $status);
        if ($status == 0) {
            echo "生成成功!";
        } else {
            echo "生成失败!状态码: " . $status;
            print_r($output);  // 查看详细的错误输出
        }

        if (file_exists($tempHtmlFile)) {
            unlink($tempHtmlFile);  // 删除临时文件
            echo "临时文件已删除";
        } else {
            echo "临时文件不存在,无法删除";
        }

杨佳乐 发布于  2025-2-28 16:30 

Java 特点 Java

public class Demo1 {

    public static void main(String[] args) {
//        Java 特点

//        1. 平台独立性
//        解释:Java 是一次编写,处处运行。它通过 Java 虚拟机(JVM)来实现平台无关性,程序在任何平台上都可以运行,只要该平台上有 Java 环境。
//        原理:Java 源代码编译后会生成字节码文件(.class),然后 JVM 解释和执行这些字节码,不直接依赖于底层操作系统。
//        2. 面向对象
//        解释:Java 是一门面向对象的编程语言,几乎所有的内容都作为对象存在。面向对象有四个基本特性:
//        封装:数据和方法被封装在对象中,外界不能直接访问对象的属性,只能通过方法来操作对象的数据。
//        继承:Java 允许类之间的继承,子类可以继承父类的属性和方法,从而实现代码重用。
//        多态:多态允许通过父类引用指向子类对象,并在运行时决定调用哪个方法。这样可以使得代码更具扩展性。
//        抽象:抽象允许你只关心对象的行为而不关心其具体实现,通常通过抽象类或接口来实现。
//        3. 简洁和易学
//        解释:Java 的语法比较简洁,比 C++ 少了指针、手动内存管理等复杂特性,学习起来相对容易。
//        优点:对初学者来说,Java 提供了清晰且易于理解的结构和语法,快速上手。
//        4. 垃圾回收机制
//        解释:Java 有自动的垃圾回收机制,JVM 会自动管理内存,定期清理不再使用的对象,减少了内存泄漏的风险。
//        原理:通过垃圾回收(GC)机制,程序员不需要手动释放内存,只需关注逻辑和性能,JVM 会自动处理内存的分配和回收。
//        5. 多线程支持
//        解释:Java 提供了内建的多线程支持,可以轻松创建多线程应用。Java 提供了线程类和接口,使得线程的管理和同步变得容易。
//        原理:Java 通过 Thread 类和 Runnable 接口来创建和管理线程,使用 synchronized 关键字来保证线程之间的同步,避免数据竞争。
//        6. 丰富的标准库
//        解释:Java 提供了大量的标准类库,涵盖了输入输出、网络、数据库、GUI、并发等各种功能。
//        优点:你可以直接使用这些库来完成常见的开发任务,而不必自己从头编写。
//        7. 安全性
//        解释:Java 的安全性设计非常严密,能够有效避免很多常见的安全问题。通过 Java 安全管理器和字节码验证机制,Java 可以有效防止恶意代码的执行。
//        原理:Java 提供了一种安全的执行环境,可以限制应用程序对系统资源的访问,防止程序执行潜在的有害操作。
//        8. 跨平台性
//        解释:Java 程序通过 JVM 实现跨平台执行,Java 程序可以在不同操作系统上运行,如 Windows、Linux、macOS 等。
//        原理:只要目标操作系统上安装了相应的 JVM,就可以执行相同的字节码。
//        9. 高性能
//        解释:Java 是一种编译型语言,编译后的字节码执行速度较快,而且随着 JVM 和垃圾回收技术的优化,Java 性能也在不断提高。
//        优化:现代的 JIT(即时编译)技术可以将热点代码编译成本地机器码,从而提高执行效率。
//        10. 大规模应用支持
//        解释:Java 具有良好的扩展性,适合开发大规模的应用,广泛应用于企业级应用、Web 开发和大数据处理等领域。

    }
}
标签: Java

杨佳乐 发布于  2025-2-24 22:07 

Golang gorm demo2 Golang

package main

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "gorm.io/gorm/schema"
    "time"
)

// 定义模型
type Admin struct {
    ID uint `gorm:"primaryKey;not null"`
    Username string `gorm:"size:100;not null"`
    Password string `gorm:"size:200;not null"`
    Nickname string `gorm:"size:100"`
    CreatedAt time.Time `gorm:"type:datetime"`
    UpdatedAt time.Time `gorm:"type:datetime"`
}

var DB *gorm.DB

func main(){

    dsn := "test:test@tcp(127.0.0.1:3306)/gormdemo1?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
        NamingStrategy: schema.NamingStrategy{
            TablePrefix:   "la_", // 设置表前缀
            SingularTable: false,      // 禁用表名复数
        },
    })
    if err != nil {
        fmt.Println("数据库连接失败")
    }

    DB = db

    // 创建表
    DB.AutoMigrate(&Admin{})

    // 添加数据
    admin1 := Admin{
        Username:"admin",
        Password:"pwd",
        Nickname:"nickadm",
    }

    DB.Create(&admin1)

    if admin1.ID > 0 {
        fmt.Println("创建成功")
    }

    var searchadm1 Admin

    DB.Find(&searchadm1,3)

    fmt.Println(searchadm1)

    if searchadm1.ID > 0 {
        DB.Delete(searchadm1)
    }

    fmt.Println("执行完成")

}

杨佳乐 发布于  2025-1-17 15:46 

Golang gorm demo1 Golang

package main

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "gorm.io/gorm/schema"
    "time"
)

// 定义用户模型
type User struct {
    ID uint `gorm:"primaryKey;not null"`
    Name string `gorm:"size:100"`
    Mobile string `gorm:"uniqueIndex;size:20"`
    CreatedAt time.Time
    UpdatedAt time.Time
}

func main(){

    dsn := "root:123456@tcp(127.0.0.1:3306)/gormdemo1?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
        NamingStrategy: schema.NamingStrategy{
            TablePrefix:   "tes_", // 设置表前缀
            SingularTable: false,      // 禁用表名复数
        },
    })
    if err != nil {
        fmt.Println("数据库连接失败: %v", err)
    }

    fmt.Println("数据库连接成功!")

    err = db.AutoMigrate(&User{})
    if err != nil {
        fmt.Println("创建User表失败: %v", err)
    }
    fmt.Println("创建User表成功")

    // 添加一条数据
    // user1 := User{
    //  Name:"user1",
    //  Mobile:"1000000000",
    // }

    // result := db.Create(&user1)

    // if result.Error != nil {
    //  fmt.Println("failed to create user: %v", result.Error)
    // }

    // fmt.Println(user1)

    // 查询数据
    var user User

    // 主键查询
    db.Find(&user,1)

    var user2 User

    // 条件查询
    db.Find(&user2,"mobile = ?","1000000000")

    fmt.Println(user)
    fmt.Println(user2)

    // 模拟动态条件
    var wheres = make(map[string]interface{})
    wheres["name"] = "test"
    wheres["mobile"] = "111"
    // wheres := map[string]interface{}{"name":"test","mobile":"1111",}

    var user3 User
    query := db.Model(&User{})
    for key,value := range wheres{

        if value != "" {
            query = query.Where(fmt.Sprintf("%s = ?", key), value)
        }
    }
    query.Find(&user3)

    var upduser User
    db.Find(&upduser,1)
    // 更新某个字段
    db.Model(&upduser).Update("mobile","123123")

    // 更新多个字段
    db.Model(&upduser).Updates(&User{Name:"aaaa",Mobile:"1000000000"})

    // 删除
    db.Delete(&upduser)

    // 查询多条数据
    var userlist []User
    db.Where("id > ?",0).Find(&userlist)
    fmt.Println(userlist)
    for k,v := range userlist {
        fmt.Println(k)
        fmt.Println(v.Name)
    }

    var orderlist []User
    // 分页及排序
    db.Order("id desc").Limit(10).Offset(0).Find(&orderlist)

    fmt.Println(orderlist)

    // 事务操作
    err = db.Transaction(func(tx *gorm.DB) error {
        if err := tx.Create(&User{Name: "User1",Mobile:"1700000111"}).Error; err != nil {
            return err
        }
        if err := tx.Create(&User{Name: "User2",Mobile:"160000"}).Error; err != nil {
            return err
        }
        return nil
    })

    if err != nil {
        fmt.Println("出现事务错误")
        fmt.Println(err)
    }

    pageFind(db)

    // 关闭连接
    mysqldb,err := db.DB()

    mysqldb.Close()

}

// 分页查询,处理总数量、总页数
func pageFind(db *gorm.DB){

    fmt.Println("进入分页方法查询")

    var totalCount int64

    query := db.Model(&User{}).Where("id > 0")

    // 查询总数量
    query.Count(&totalCount)

    // 查询当前页数据
    var list []User

    pageSize := 2
    currentPage := 0

    db.Limit(pageSize).Offset(currentPage).Find(&list)

    // 计算总页数
    totalPages := (totalCount + int64(pageSize) - 1) / int64(pageSize)

    fmt.Println("分页查询完毕")
    fmt.Println(list)
    fmt.Println("总数量",totalCount,"总页数",totalPages)
}

杨佳乐 发布于  2025-1-17 13:51 

Golang gorm包 Golang

package main

// gorm 官方文档
// https://gorm.io/zh_CN/docs/

// 安装gorm
// go get -u gorm.io/gorm
// go get -u gorm.io/driver/mysql

// 如果因网络问题无法安装,尝试更换网络源
// 设置清华大学源
// go env -w GOPROXY=https://goproxy.cn,direct

// 初始化数据库连接
// import (
//  "gorm.io/driver/mysql"
//  "gorm.io/gorm"
//  "log"
// )

// func main() {
//  dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
//  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
//  if err != nil {
//      log.Fatalf("failed to connect database: %v", err)
//  }

//  log.Println("Database connected successfully!")
// }
// dsn:数据源名称,需要替换 user、password 和 dbname。
// gorm.Config{}:GORM 的配置选项。

// 定义模型
// 定义与数据库表对应的模型
// type User struct {
//  ID        uint   `gorm:"primaryKey"`
//  Name      string `gorm:"size:100"`
//  Email     string `gorm:"uniqueIndex;size:100"`
//  CreatedAt time.Time
//  UpdatedAt time.Time
//  DeletedAt gorm.DeletedAt `gorm:"index"`
// }

// 迁移表结构
// 使用 GORM 的自动迁移功能创建表
// err = db.AutoMigrate(&User{})
// if err != nil {
//  log.Fatalf("failed to migrate database: %v", err)
// }
// log.Println("Database migrated successfully!")

// 基本操作
// 1.创建数据
// user := User{Name: "John Doe", Email: "john.doe@example.com"}
// result := db.Create(&user)

// if result.Error != nil {
//  log.Fatalf("failed to create user: %v", result.Error)
// }

// log.Printf("User created successfully: %+v", user)

// 2.查询记录
// var user User
// db.First(&user, 1) // 根据主键查询
// db.First(&user, "email = ?", "john.doe@example.com") // 条件查询

// log.Printf("User found: %+v", user)

// 3.更新记录
// db.Model(&user).Update("Name", "Jane Doe")
// db.Model(&user).Updates(User{Name: "Jane Doe", Email: "jane.doe@example.com"}) // 批量更新

// 4.删除记录
// db.Delete(&user) // 根据主键删除

// 高级功能
// 1.查询多条数据
// var users []User
// db.Where("name LIKE ?", "%Doe%").Find(&users)
// log.Printf("Users found: %+v", users)

// 2.分页和排序
// var users []User
// db.Order("created_at desc").Limit(10).Offset(0).Find(&users) // 分页

// 3.事务支持
// err = db.Transaction(func(tx *gorm.DB) error {
//  if err := tx.Create(&User{Name: "User1"}).Error; err != nil {
//      return err
//  }
//  if err := tx.Create(&User{Name: "User2"}).Error; err != nil {
//      return err
//  }
//  return nil
// })
// if err != nil {
//  log.Fatalf("Transaction failed: %v", err)
// }

// 常用配置
// 在初始化时配置 GORM 的行为
// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
//  Logger: logger.Default.LogMode(logger.Info), // 显示详细的 SQL 日志
// })

// 字段级权限控制
// type User struct {
//  Name string `gorm:"<-:create"` // 允许读和创建
//  Name string `gorm:"<-:update"` // 允许读和更新
//  Name string `gorm:"<-"`        // 允许读和写(创建和更新)
//  Name string `gorm:"<-:false"`  // 允许读,禁止写
//  Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)
//  Name string `gorm:"->;<-:create"` // 允许读和写
//  Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
//  Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段
//  Name string `gorm:"-:all"`        // 通过 struct 读写、迁移会忽略该字段
//  Name string `gorm:"-:migration"`  // 通过 struct 迁移会忽略该字段
//   }

// 创建/更新时间追踪(纳秒、毫秒、秒、Time)
// GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间
// 要使用不同名称的字段,您可以配置 autoCreateTime、autoUpdateTime 标签。
// 如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可
// type User struct {
//  CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
//  UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
//  Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳纳秒数填充更新时间
//  Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
//  Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间
//   }

//字段标签
// column   指定 db 列名
// type 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null、size, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT
// serializer   指定将数据序列化或反序列化到数据库中的序列化器, 例如: serializer:json/gob/unixtime
// size 定义列数据类型的大小或长度,例如 size: 256
// primaryKey   将列定义为主键
// unique   将列定义为唯一键
// default  定义列的默认值
// precision    指定列的精度
// scale    指定列大小
// not null 指定列为 NOT NULL
// autoIncrement    指定列为自动增长
// autoIncrementIncrement   自动步长,控制连续记录之间的间隔
// embedded 嵌套字段
// embeddedPrefix   嵌入字段的列名前缀
// autoCreateTime   创建时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano
// autoUpdateTime   创建/更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
// index    根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情
// uniqueIndex  与 index 相同,但创建的是唯一索引
// check    创建检查约束,例如 check:age > 13,查看 约束 获取详情
// <-   设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限
// ->   设置字段读的权限,->:false 无读权限
// -    忽略该字段,- 表示无读写,-:migration 表示无迁移权限,-:all 表示无读写迁移权限
// comment  迁移时为字段添加注释

// 配置表前缀
// dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
//  NamingStrategy: schema.NamingStrategy{
//      TablePrefix:   "prefix_", // 设置表前缀
//      SingularTable: true,      // 禁用表名复数
//  },
//  Logger: logger.Default.LogMode(logger.Info),
// })
// TablePrefix:设置表前缀,例如 prefix_。
// SingularTable:
// 默认情况下,GORM 会将模型名转换为复数形式(如 User -> users)。
// 设置为 true 后,表名将保持单数形式。

// 自定义表名
// 对某个模型单独设置表名,可以实现 TableName 方法
// type User struct {
//     ID   uint
//     Name string
// }

// func (User) TableName() string {
//     return "custom_user_table"
// }

// 其他常见配置
// sqlDB, _ := db.DB()
// sqlDB.SetMaxIdleConns(10) // 设置空闲连接数
// sqlDB.SetMaxOpenConns(100) // 设置最大连接数
// sqlDB.SetConnMaxLifetime(time.Hour) // 设置连接的最大生命周期

// 配置日志输出
// 可以定制 GORM 的日志行为,例如输出到文件

// file, _ := os.Create("gorm.log")
// newLogger := logger.New(
//     log.New(file, "\r\n", log.LstdFlags),
//     logger.Config{
//         SlowThreshold: time.Second,   // 慢查询阈值
//         LogLevel:      logger.Warn,   // 日志级别
//         IgnoreRecordNotFoundError: true,
//     },
// )

// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
//     Logger: newLogger,
// })

// 完整配置总结
    // dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    // db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
    //  SkipDefaultTransaction: true, // 跳过默认事务
    //  NamingStrategy: schema.NamingStrategy{
    //      TablePrefix:   "prefix_", // 设置表前缀
    //      SingularTable: true,      // 禁用表名复数
    //  },
    //  Logger: logger.Default.LogMode(logger.Info), // 显示详细日志
    // })

    // if err != nil {
    //  log.Fatalf("failed to connect database: %v", err)
    // }

    // // 配置连接池
    // sqlDB, _ := db.DB()
    // sqlDB.SetMaxIdleConns(10)
    // sqlDB.SetMaxOpenConns(100)
    // sqlDB.SetConnMaxLifetime(time.Hour)

    // log.Println("Database connected successfully!")

func main(){

}

杨佳乐 发布于  2025-1-17 10:49