opc

package module
v0.7.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 1, 2023 License: BSD-2-Clause Imports: 12 Imported by: 1

README

opc

PkgGoDev Build Status Go Report Card codecov codeclimate License Mentioned in Awesome Go

Package opc implements the ISO/IEC 29500-2, also known as the Open Packaging Convention.

The Open Packaging specification describes an abstract model and physical format conventions for the use of XML, Unicode, ZIP, and other openly available technologies and specifications to organize the content and resources of a document within a package.

The OPC is the foundation technology for many new file formats: .docx, .pptx, .xlsx, .3mf, .dwfx, ...

Features

  • Package reader and writer
  • Package core properties and relationships
  • Part relationships
  • ZIP mapping
  • Package, relationships and parts validation against specs
  • Part interleaved pieces
  • Digital signatures

Examples

Write
// Create a file to write our archive to.
f, _ := os.Create("example.xlsx")

// Create a new OPC archive.
w := opc.NewWriter(f)

// Create a new OPC part.
name := opc.NormalizePartName("docs\\readme.txt")
part, _ := w.Create(name, "text/plain")

// Write content to the part.
part.Write([]byte("This archive contains some text files."))

// Make sure to check the error on Close.
w.Close()
Read
r, _ := opc.OpenReader("testdata/test.xlsx")
defer r.Close()

// Iterate through the files in the archive,
// printing some of their contents.
for _, f := range r.Files {
  fmt.Printf("Contents of %s with type %s :\n", f.Name, f.ContentType)
  rc, _ := f.Open()
  io.CopyN(os.Stdout, rc, 68)
  rc.Close()
  fmt.Println()
}

Documentation

Overview

Package opc implements the ISO/IEC 29500-2, also known as the "Open Packaging Convention".

The Open Packaging specification describes an abstract model and physical format conventions for the use of XML, Unicode, ZIP, and other openly available technologies and specifications to organize the content and resources of a document within a package.

The OPC is the foundation technology for many new file formats: .docx, .pptx, .xlsx, .3mf, .dwfx, ...

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NormalizePartName

func NormalizePartName(name string) string

NormalizePartName transforms the input name as an URI string so it follows the constrains specified in the ISO/IEC 29500-2 §9.1.1. This method is recommended to be used before adding a new Part to a package to avoid errors. If, for whatever reason, the name can't be adapted to the specs, the return value is empty. Warning: This method can heavily modify the name if it differs a lot from the specs, which could led to duplicated part names.

func ResolveRelationship added in v0.6.4

func ResolveRelationship(source string, rel string) string

ResolveRelationship returns the absolute URI (from the package root) of the part pointed by a relationship of a source part. This method should be used in places where we have a target relationship URI and we want to get the name of the part it targets with respect to the source part. The source can be a valid part URI, for part relationships, or "/", for package relationships.

Types

type CompressionOption

type CompressionOption int

CompressionOption is an enumerable for the different compression options.

const (
	// CompressionNone disables the compression.
	CompressionNone CompressionOption = iota - 1
	// CompressionNormal is optimized for a reasonable compromise between size and performance.
	CompressionNormal
	// CompressionMaximum is optimized for size.
	CompressionMaximum
	// CompressionFast is optimized for performance.
	CompressionFast
	// CompressionSuperFast is optimized for super performance.
	CompressionSuperFast
)

type CoreProperties

type CoreProperties struct {
	PartName       string // Won't be written to the package, only used to indicate the location of the CoreProperties part. If empty the default location is "/props/core.xml".
	RelationshipID string // Won't be written to the package, only used to indicate the relationship ID for target "/props/core.xml".
	Category       string // A categorization of the content of this package.
	ContentStatus  string // The status of the content.
	Created        string // Date of creation of the resource.
	Creator        string // An entity primarily responsible for making the content of the resource.
	Description    string // An explanation of the content of the resource.
	Identifier     string // An unambiguous reference to the resource within a given context.
	Keywords       string // A delimited set of keywords to support searching and indexing.
	Language       string // The language of the intellectual content of the resource.
	LastModifiedBy string // The user who performed the last modification.
	LastPrinted    string // The date and time of the last printing.
	Modified       string // Date on which the resource was changed.
	Revision       string // The revision number.
	Subject        string // The topic of the content of the resource.
	Title          string // The name given to the resource.
	Version        string // The version number.
}

CoreProperties enable users to get and set well-known and common sets of property metadata within packages.

type Error

type Error struct {
	// contains filtered or unexported fields
}

An Error from this package is always associated to an OPC entity that is not conformant with the OPC specs.

func (*Error) Code

func (e *Error) Code() int

Code of the error as described in the OPC specs. The first number is the top level topic and the second and third digits are the specific error code. The top level topics are described as follows: 1. Package Model requirements 2. Physical Packages requirements 3. ZIP Physical Mapping requirements 4. Core Properties requirements 5. Thumbnail requirements 6. Digital Signatures requirements 7. Pack URI requirements

func (*Error) Error

func (e *Error) Error() string

func (*Error) PartName

func (e *Error) PartName() string

PartName returns the name of the Part associated to the error.

func (*Error) RelationshipID

func (e *Error) RelationshipID() string

RelationshipID returns the ID of the relationship associated to the error. If the error is not associated to a relationship, the value is empty.

type File

type File struct {
	*Part
	Size int
	// contains filtered or unexported fields
}

File is used to read a part from the OPC package.

func (*File) Open

func (f *File) Open() (io.ReadCloser, error)

Open returns a ReadCloser that provides access to the File's contents. Multiple files may be read concurrently.

type Part

type Part struct {
	Name          string          // The name of the part.
	ContentType   string          // The type of content stored in the part.
	Relationships []*Relationship // The relationships associated to the part. Can be modified until the Writer is closed.
}

A Part is a stream of bytes defined in ISO/IEC 29500-2 §9.1.. Parts are analogous to a file in a file system or to a resource on an HTTP server.

type ReadCloser

type ReadCloser struct {
	*Reader
	// contains filtered or unexported fields
}

ReadCloser wrapps a Reader than can be closed.

func OpenReader

func OpenReader(name string) (*ReadCloser, error)

OpenReader will open the OPC file specified by name and return a ReadCloser.

func (*ReadCloser) Close

func (r *ReadCloser) Close() error

Close closes the OPC file, rendering it unusable for I/O.

type Reader

type Reader struct {
	Files         []*File
	Relationships []*Relationship
	Properties    CoreProperties
	// contains filtered or unexported fields
}

Reader implements a OPC file reader.

Example
package main

import (
	"fmt"
	"io"
	"log"
	"os"

	"github.com/qmuntal/opc"
)

func main() {
	r, err := opc.OpenReader("testdata/component.3mf")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close()

	// Iterate through the files in the archive,
	// printing some of their contents.
	for _, f := range r.Files {
		fmt.Printf("Contents of %s with type %s :\n", f.Name, f.ContentType)
		rc, err := f.Open()
		if err != nil {
			log.Fatal(err)
		}
		_, err = io.CopyN(os.Stdout, rc, 68)
		if err != nil {
			log.Fatal(err)
		}
		rc.Close()
		fmt.Println()
	}
}
Output:

func NewReader

func NewReader(r io.ReaderAt, size int64) (*Reader, error)

NewReader returns a new Reader reading an OPC file to r.

func (*Reader) SetDecompressor added in v0.6.4

func (r *Reader) SetDecompressor(dcomp func(r io.Reader) io.ReadCloser)

SetDecompressor sets or overrides a custom decompressor for the DEFLATE.

type Relationship

type Relationship struct {
	ID         string     // The relationship identifier which shall conform the xsd:ID naming restrictions and unique within the part.
	Type       string     // Defines the role of the relationship.
	TargetURI  string     // Holds a URI that points to a target resource. If expressed as a relative URI, it is resolved against the base URI of the Relationships source part.
	TargetMode TargetMode // Indicates whether or not the target describes a resource inside the package or outside the package.
}

Relationship is used to express a relationship between a source and a target part. If the ID is not specified a unique ID will be generated following the pattern rIdN. If the TargetMode is not specified the default value is Internal. Defined in ISO/IEC 29500-2 §9.3.

type TargetMode

type TargetMode int

TargetMode is an enumerable for the different target modes.

const (
	// ModeInternal when the target targetMode is Internal (default value).
	// Target points to a part within the package and target uri must be relative.
	ModeInternal TargetMode = iota
	// ModeExternal when the target targetMode is External.
	// Target points to an external resource and target uri can be relative or absolute.
	ModeExternal
)

type Writer

type Writer struct {
	Properties    CoreProperties  // Package metadata. Can be modified until the Writer is closed.
	Relationships []*Relationship // The relationships associated to the package. Can be modified until the Writer is closed.
	// contains filtered or unexported fields
}

Writer implements a OPC file writer.

Example
package main

import (
	"bytes"
	"log"

	"github.com/qmuntal/opc"
)

func main() {
	// Create a buffer to write our archive to.
	buf := new(bytes.Buffer)

	// Create a new OPC archive.
	w := opc.NewWriter(buf)

	// Create a new OPC part.
	name := opc.NormalizePartName("docs\\readme.txt")
	part, err := w.Create(name, "text/plain")
	if err != nil {
		log.Fatal(err)
	}

	// Write content to the part.
	_, err = part.Write([]byte("This archive contains some text files."))
	if err != nil {
		log.Fatal(err)
	}

	// Make sure to check the error on Close.
	if err := w.Close(); err != nil {
		log.Fatal(err)
	}
}
Output:

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter returns a new Writer writing an OPC package to w.

func NewWriterFromReader added in v0.7.6

func NewWriterFromReader(w io.Writer, r *Reader) (*Writer, error)

NewWriterFromReader returns a new Writer writing an OPC package to w and with its content initialized with r.

The original package is not modified. Parts coming from r cannot be modified but new parts can be appended and package core properties and relationships can be updated.

Example
package main

import (
	"bytes"
	"log"

	"github.com/qmuntal/opc"
)

func main() {
	r, err := opc.OpenReader("testdata/component.3mf")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close()

	buf := new(bytes.Buffer)
	w, err := opc.NewWriterFromReader(buf, r.Reader)
	if err != nil {
		log.Fatal(err)
	}
	name := opc.NormalizePartName("docs\\readme.txt")
	part, err := w.Create(name, "text/plain")
	if err != nil {
		log.Fatal(err)
	}

	// Write content to the part.
	_, err = part.Write([]byte("This archive contains some text files."))
	if err != nil {
		log.Fatal(err)
	}

	// Make sure to check the error on Close.
	if err := w.Close(); err != nil {
		log.Fatal(err)
	}
}
Output:

func (*Writer) Close

func (w *Writer) Close() error

Close finishes writing the opc file. It does not close the underlying writer.

func (*Writer) Create

func (w *Writer) Create(name, contentType string) (io.Writer, error)

Create adds a file to the OPC archive using the provided name and content type. The file contents will be compressed using the Deflate default method. The name shall be a valid part name, one can use NormalizePartName before calling Create to normalize it

This returns a Writer to which the file contents should be written. The file's contents must be written to the io.Writer before the next call to Create, CreatePart, or Close.

func (*Writer) CreatePart

func (w *Writer) CreatePart(part *Part, compression CompressionOption) (io.Writer, error)

CreatePart adds a file to the OPC archive using the provided part. The name shall be a valid part name, one can use NormalizePartName before calling CreatePart to normalize it. Writer takes ownership of part and may mutate all its fields except the Relationships, which can be modified until the next call to Create, CreatePart or Close. The caller must not modify part after calling CreatePart, except the Relationships.

This returns a Writer to which the file contents should be written. The file's contents must be written to the io.Writer before the next call to Create, CreatePart, or Close.

func (*Writer) Flush

func (w *Writer) Flush() error

Flush flushes any buffered data to the underlying writer. Part metadata, relationships, content types and other OPC related files won't be flushed. Calling Flush is not normally necessary; calling Close is sufficient. Useful to do simultaneous writing and reading.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL