( fileSpec: PdfDict, name: string, resolver: RefResolver, )
| 166 | * @returns AttachmentInfo or null if external file reference |
| 167 | */ |
| 168 | export function parseFileSpec( |
| 169 | fileSpec: PdfDict, |
| 170 | name: string, |
| 171 | resolver: RefResolver, |
| 172 | ): AttachmentInfo | null { |
| 173 | // Get the embedded file stream |
| 174 | const stream = getEmbeddedFileStream(fileSpec, resolver); |
| 175 | |
| 176 | if (!stream) { |
| 177 | // External file reference - we don't support these |
| 178 | return null; |
| 179 | } |
| 180 | |
| 181 | const info: AttachmentInfo = { |
| 182 | name, |
| 183 | filename: getFilename(fileSpec), |
| 184 | }; |
| 185 | |
| 186 | // Get description |
| 187 | const desc = fileSpec.getString("Desc"); |
| 188 | |
| 189 | if (desc) { |
| 190 | info.description = desc.asString(); |
| 191 | } |
| 192 | |
| 193 | // Get MIME type from stream's /Subtype |
| 194 | const subtype = stream.getName("Subtype"); |
| 195 | |
| 196 | if (subtype) { |
| 197 | // /Subtype is a name like /application#2Fpdf |
| 198 | // Need to decode the # sequences |
| 199 | info.mimeType = subtype.value.replaceAll("#2F", "/").replaceAll("#20", " "); |
| 200 | } |
| 201 | |
| 202 | // Get params from stream |
| 203 | const params = stream.getDict("Params", resolver); |
| 204 | |
| 205 | if (params) { |
| 206 | // Size |
| 207 | const size = params.getNumber("Size"); |
| 208 | |
| 209 | if (size) { |
| 210 | info.size = size.value; |
| 211 | } |
| 212 | |
| 213 | // Creation date |
| 214 | const creationDate = params.getString("CreationDate"); |
| 215 | |
| 216 | if (creationDate) { |
| 217 | info.createdAt = parsePdfDate(creationDate.asString()); |
| 218 | } |
| 219 | |
| 220 | // Modification date |
| 221 | const modDate = params.getString("ModDate"); |
| 222 | |
| 223 | if (modDate) { |
| 224 | info.modifiedAt = parsePdfDate(modDate.asString()); |
| 225 | } |
no test coverage detected