mirror of
https://github.com/ZeroHawkeye/wordZero.git
synced 2025-09-26 20:01:17 +08:00
- 修复文档id不是唯一的问题,遵循ooxml规范
This commit is contained in:
@@ -29,6 +29,8 @@ type Document struct {
|
||||
styleManager *style.StyleManager
|
||||
// 临时存储文档部件
|
||||
parts map[string][]byte
|
||||
// 图片ID计数器,确保每个图片都有唯一的ID
|
||||
nextImageID int
|
||||
}
|
||||
|
||||
// Body 表示文档主体
|
||||
@@ -351,7 +353,7 @@ type NumID struct {
|
||||
Val string `xml:"w:val,attr"`
|
||||
}
|
||||
|
||||
// New 创建一个新的空文档
|
||||
// New 创建一个新的Word文档
|
||||
func New() *Document {
|
||||
Debugf("创建新文档")
|
||||
|
||||
@@ -361,13 +363,16 @@ func New() *Document {
|
||||
},
|
||||
styleManager: style.NewStyleManager(),
|
||||
parts: make(map[string][]byte),
|
||||
nextImageID: 1, // 初始化图片ID计数器,从1开始
|
||||
documentRelationships: &Relationships{
|
||||
Xmlns: "http://schemas.openxmlformats.org/package/2006/relationships",
|
||||
Relationships: []Relationship{},
|
||||
},
|
||||
}
|
||||
|
||||
// 初始化文档结构
|
||||
doc.initializeStructure()
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
@@ -409,6 +414,7 @@ func Open(filename string) (*Document, error) {
|
||||
Xmlns: "http://schemas.openxmlformats.org/package/2006/relationships",
|
||||
Relationships: []Relationship{},
|
||||
},
|
||||
nextImageID: 1, // 初始化图片ID计数器
|
||||
}
|
||||
|
||||
// 读取所有文件部件
|
||||
|
@@ -426,10 +426,12 @@ func (d *Document) AddImageFromData(imageData []byte, fileName string, format Im
|
||||
}
|
||||
}
|
||||
|
||||
// 生成关系ID和图片ID
|
||||
// 注意:rId1保留给styles.xml,图片从rId2开始
|
||||
// 使用文档级别的图片ID计数器确保ID唯一性
|
||||
imageID := d.nextImageID
|
||||
d.nextImageID++ // 递增计数器
|
||||
|
||||
// 生成关系ID,注意:rId1保留给styles.xml,图片从rId2开始
|
||||
relationID := fmt.Sprintf("rId%d", len(d.documentRelationships.Relationships)+2)
|
||||
imageID := len(d.documentRelationships.Relationships) + 1
|
||||
|
||||
// 添加图片关系
|
||||
d.documentRelationships.Relationships = append(d.documentRelationships.Relationships, Relationship{
|
||||
@@ -465,6 +467,54 @@ func (d *Document) AddImageFromData(imageData []byte, fileName string, format Im
|
||||
return imageInfo, nil
|
||||
}
|
||||
|
||||
// AddImageFromDataWithoutElement 从数据添加图片到文档但不创建段落元素
|
||||
// 此方法供模板引擎等需要自行管理图片段落的场景使用
|
||||
func (d *Document) AddImageFromDataWithoutElement(imageData []byte, fileName string, format ImageFormat, width, height int, config *ImageConfig) (*ImageInfo, error) {
|
||||
if d.documentRelationships == nil {
|
||||
d.documentRelationships = &Relationships{
|
||||
Xmlns: "http://schemas.openxmlformats.org/package/2006/relationships",
|
||||
Relationships: []Relationship{},
|
||||
}
|
||||
}
|
||||
|
||||
// 使用文档级别的图片ID计数器确保ID唯一性
|
||||
imageID := d.nextImageID
|
||||
d.nextImageID++ // 递增计数器
|
||||
|
||||
// 生成关系ID,注意:rId1保留给styles.xml,图片从rId2开始
|
||||
relationID := fmt.Sprintf("rId%d", len(d.documentRelationships.Relationships)+2)
|
||||
|
||||
// 添加图片关系
|
||||
d.documentRelationships.Relationships = append(d.documentRelationships.Relationships, Relationship{
|
||||
ID: relationID,
|
||||
Type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
||||
Target: fmt.Sprintf("media/%s", fileName),
|
||||
})
|
||||
|
||||
// 存储图片数据
|
||||
if d.parts == nil {
|
||||
d.parts = make(map[string][]byte)
|
||||
}
|
||||
d.parts[fmt.Sprintf("word/media/%s", fileName)] = imageData
|
||||
|
||||
// 更新内容类型
|
||||
d.addImageContentType(format)
|
||||
|
||||
// 创建图片信息
|
||||
imageInfo := &ImageInfo{
|
||||
ID: strconv.Itoa(imageID),
|
||||
RelationID: relationID,
|
||||
Format: format,
|
||||
Width: width,
|
||||
Height: height,
|
||||
Data: imageData,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// 注意:这个方法不创建段落元素,由调用者负责管理
|
||||
return imageInfo, nil
|
||||
}
|
||||
|
||||
// createImageParagraph 创建包含图片的段落
|
||||
func (d *Document) createImageParagraph(imageInfo *ImageInfo) *Paragraph {
|
||||
// 计算图片显示尺寸(EMU单位)
|
||||
|
@@ -3,6 +3,8 @@ package document
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -2517,11 +2519,31 @@ func (te *TemplateEngine) createImageParagraph(imageData *TemplateImageData, doc
|
||||
return nil, fmt.Errorf("获取图片尺寸失败: %v", err)
|
||||
}
|
||||
|
||||
fileName := fmt.Sprintf("image_%d.%s", len(doc.documentRelationships.Relationships)+1, string(format))
|
||||
imageInfo, err = doc.AddImageFromData(imageData.Data, fileName, format, width, height, config)
|
||||
// 使用唯一的文件名,包含图片ID计数器
|
||||
fileName := fmt.Sprintf("image_%d.%s", doc.nextImageID, string(format))
|
||||
// 使用不创建段落元素的方法,由模板引擎自行管理段落
|
||||
imageInfo, err = doc.AddImageFromDataWithoutElement(imageData.Data, fileName, format, width, height, config)
|
||||
} else if imageData.FilePath != "" {
|
||||
// 使用文件路径
|
||||
imageInfo, err = doc.AddImageFromFile(imageData.FilePath, config)
|
||||
// 使用文件路径,但需要先读取数据,然后使用AddImageFromDataWithoutElement
|
||||
data, readErr := os.ReadFile(imageData.FilePath)
|
||||
if readErr != nil {
|
||||
return nil, fmt.Errorf("读取图片文件失败: %v", readErr)
|
||||
}
|
||||
|
||||
var format ImageFormat
|
||||
format, err = detectImageFormat(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("检测图片格式失败: %v", err)
|
||||
}
|
||||
|
||||
var width, height int
|
||||
width, height, err = getImageDimensions(data, format)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取图片尺寸失败: %v", err)
|
||||
}
|
||||
|
||||
fileName := filepath.Base(imageData.FilePath)
|
||||
imageInfo, err = doc.AddImageFromDataWithoutElement(data, fileName, format, width, height, config)
|
||||
} else {
|
||||
return nil, fmt.Errorf("图片数据和文件路径都为空")
|
||||
}
|
||||
|
Reference in New Issue
Block a user