Class: HexaPDF::Type::FileSpecification
- Inherits:
-
Dictionary
- Object
- Object
- Dictionary
- HexaPDF::Type::FileSpecification
- Defined in:
- lib/hexapdf/type/file_specification.rb
Overview
Represents a file specification dictionary.
File specifications are used to refer to other files or URLs from within a PDF file. Simple file specifications are just strings. However, the are automatically converted on access to a full file specification to provide a unified interface.
Working with File Specifications
A file specification may refer to a file or an URL. This can easily be checked with #url?. Independent of whether the file specification referes to an URL or a file, the #path method returns the “best” useable path for it.
Modifying a file specification should be done via the #path= and #url= methods as they ensure that no obsolescent entries are used and the file specification is consistent.
Finally, since embedded files in a PDF document are always linked to a file specification it is useful to provide embedding/unembedding operations in this class, see #embed and #unembed.
See: PDF1.7 s7.11
Defined Under Namespace
Classes: EFDictionary
Constant Summary
Constants included from DictionaryFields
DictionaryFields::Boolean, DictionaryFields::PDFByteString, DictionaryFields::PDFDate
Constants inherited from Object
Object::NOT_DUPLICATABLE_CLASSES
Instance Attribute Summary
Attributes inherited from Object
#data, #document, #must_be_indirect
Instance Method Summary collapse
-
#embed(file_or_io, name: nil, register: true) ⇒ Object
:call-seq: file_spec.embed(filename, name: File.basename(filename), register: true) -> ef_stream file_spec.embed(io, name:, register: true) -> ef_stream.
-
#embedded_file? ⇒ Boolean
Returns
true
if this file specification contains an embedded file. -
#embedded_file_stream ⇒ Object
Returns the embedded file associated with this file specification, or
nil
if this file specification references no embedded file. -
#path ⇒ Object
Returns the path for the referenced file or URL.
-
#path=(filename) ⇒ Object
Sets the file specification string to the given filename.
-
#unembed ⇒ Object
Deletes any embedded file streams associated with this file specification.
-
#url=(url) ⇒ Object
Sets the file specification string to the given URL and updates the file system entry appropriately.
-
#url? ⇒ Boolean
Returns
true
if this file specification references an URL and not a file.
Methods inherited from Dictionary
#[], #[]=, define_field, #delete, #each, each_field, #empty?, field, #key?, #to_hash, #type
Methods inherited from Object
#<=>, #==, deep_copy, #deep_copy, #document?, #eql?, #gen, #gen=, #hash, #indirect?, #initialize, #inspect, #must_be_indirect?, #null?, #oid, #oid=, #type, #validate, #value, #value=
Constructor Details
This class inherits a constructor from HexaPDF::Object
Instance Method Details
#embed(file_or_io, name: nil, register: true) ⇒ Object
:call-seq:
file_spec.embed(filename, name: File.basename(filename), register: true) -> ef_stream
file_spec.embed(io, name:, register: true) -> ef_stream
Embeds the given file or IO stream into the PDF file, sets the path accordingly and returns the created stream object.
If a file is given, the name
option defaults to the basename of the file. However, if an IO object is given, the name
argument is mandatory.
If there already was a file embedded for this file specification, it is unembedded first.
The embedded file stream automatically uses the FlateEncode filter for compressing the embedded file.
Options:
- name
-
The name that should be used as path value and when registering.
- register
-
Specifies whether the embedded file will be added to the EmbeddedFiles name tree under the
name
. If the name is already taken, it’s value is overwritten.
The file has to be available until the PDF document gets written because reading and writing is done lazily.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/hexapdf/type/file_specification.rb', line 185 def (file_or_io, name: nil, register: true) name ||= File.basename(file_or_io) if file_or_io.kind_of?(String) if name.nil? raise ArgumentError, "The name argument is mandatory when given an IO object" end self.path = name self[:EF] ||= {} ef_stream = self[:EF][:UF] = self[:EF][:F] = document.add(Type: :EmbeddedFile) stat = if file_or_io.kind_of?(String) File.stat(file_or_io) elsif file_or_io.respond_to?(:stat) file_or_io.stat end if stat ef_stream[:Params] = {Size: stat.size, CreationDate: stat.ctime, ModDate: stat.mtime} end ef_stream.set_filter(:FlateDecode) ef_stream.stream = HexaPDF::StreamData.new(file_or_io) if register (document.catalog[:Names] ||= {})[:EmbeddedFiles] ||= {} document.catalog[:Names][:EmbeddedFiles].add_entry(name, self) end ef_stream end |
#embedded_file? ⇒ Boolean
Returns true
if this file specification contains an embedded file.
See: #embedded_file_stream
144 145 146 |
# File 'lib/hexapdf/type/file_specification.rb', line 144 def key?(:EF) && !self[:EF].empty? end |
#embedded_file_stream ⇒ Object
Returns the embedded file associated with this file specification, or nil
if this file specification references no embedded file.
If there are multiple possible embedded files, the /EF fields are searched in the following order and the first one with a value is used: /UF, /F, /Unix, /Mac, /DOS.
153 154 155 156 157 |
# File 'lib/hexapdf/type/file_specification.rb', line 153 def return unless key?(:EF) ef = self[:EF] ef[:UF] || ef[:F] || ef[:Unix] || ef[:Mac] || ef[:DOS] end |
#path ⇒ Object
Returns the path for the referenced file or URL. An empty string is returned if no file specification string is set.
If multiple file specification strings are available, the fields are search in the following order and the first one with a value is used: /UF, /F, /Unix, /Mac, /DOS.
The encoding of the returned path string is either UTF-8 (for /UF) or BINARY (for /F /Unix, /Mac and /DOS).
108 109 110 111 112 113 |
# File 'lib/hexapdf/type/file_specification.rb', line 108 def path tmp = (self[:UF] || self[:F] || self[:Unix] || self[:Mac] || self[:DOS] || '').dup tmp.gsub!(/\\\//, "/") # PDF1.7 s7.11.2.1 but / in filename is interpreted as separator! tmp.gsub!(/\\/, "/") # always use slashes instead of back-slashes! tmp end |
#path=(filename) ⇒ Object
Sets the file specification string to the given filename.
Since the /Unix, /Mac and /DOS fields are obsolescent, only the /F and /UF fields are set.
118 119 120 121 122 123 124 |
# File 'lib/hexapdf/type/file_specification.rb', line 118 def path=(filename) self[:UF] = self[:F] = filename delete(:FS) delete(:Unix) delete(:Mac) delete(:DOS) end |
#unembed ⇒ Object
Deletes any embedded file streams associated with this file specification. A possible entry in the EmbeddedFiles name tree is also deleted.
217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/hexapdf/type/file_specification.rb', line 217 def return unless key?(:EF) self[:EF].each {|_key, ef_stream| document.delete(ef_stream)} if document.catalog.key?(:Names) && document.catalog[:Names].key?(:EmbeddedFiles) tree = document.catalog[:Names][:EmbeddedFiles] tree.each_entry.find_all {|_, spec| document.deref(spec) == self}.each do |name, _| tree.delete_entry(name) end end end |
#url=(url) ⇒ Object
Sets the file specification string to the given URL and updates the file system entry appropriately.
The provided URL needs to be in an RFC1738 compliant string representation. If not, an error is raised.
131 132 133 134 135 136 137 138 139 |
# File 'lib/hexapdf/type/file_specification.rb', line 131 def url=(url) begin URI(url) rescue URI::InvalidURIError => e raise HexaPDF::Error.new(e) end self.path = url self[:FS] = :URL end |
#url? ⇒ Boolean
Returns true
if this file specification references an URL and not a file.
96 97 98 |
# File 'lib/hexapdf/type/file_specification.rb', line 96 def url? self[:FS] == :URL end |