| 207 | * @returns {Promise<Buffer|null>} Buffer containing the extracted file. Null if the file was not found. | 207 | * @returns {Promise<Buffer|null>} Buffer containing the extracted file. Null if the file was not found. |
| 208 | */ | 208 | */ |
| 209 | export async function extractFileFromZipBuffer(archiveBuffer, fileExtension) { | 209 | export async function extractFileFromZipBuffer(archiveBuffer, fileExtension) { |
| 210 | return await new Promise((resolve, reject) => yauzl.fromBuffer(Buffer.from(archiveBuffer), { lazyEntries: true }, (err, zipfile) => { | 210 | return await new Promise((resolve) => { |
| 211 | if (err) reject(err); | 211 | try { |
| 212 | | 212 | yauzl.fromBuffer(Buffer.from(archiveBuffer), { lazyEntries: true }, (err, zipfile) => { |
| 213 | zipfile.readEntry(); | 213 | if (err) { |
| 214 | zipfile.on('entry', (entry) => { | 214 | console.warn(`Error opening ZIP file: ${err.message}`); |
| 215 | if (entry.fileName.endsWith(fileExtension) && !entry.fileName.startsWith('__MACOSX')) { | 215 | return resolve(null); |
| 216 | console.info(`Extracting ${entry.fileName}`); | 216 | } |
| 217 | zipfile.openReadStream(entry, (err, readStream) => { | 217 | |
| 218 | if (err) { | 218 | zipfile.readEntry(); |
| 219 | reject(err); | 219 | |
| 220 | } else { | 220 | zipfile.on('entry', (entry) => { |
| 221 | const chunks = []; | 221 | if (entry.fileName.endsWith(fileExtension) && !entry.fileName.startsWith('__MACOSX')) { |
| 222 | readStream.on('data', (chunk) => { | 222 | console.info(`Extracting ${entry.fileName}`); |
| 223 | chunks.push(chunk); | 223 | zipfile.openReadStream(entry, (err, readStream) => { |
| 224 | }); | 224 | if (err) { |
| | 225 | console.warn(`Error opening read stream: ${err.message}`); |
| | 226 | return zipfile.readEntry(); |
| | 227 | } else { |
| | 228 | const chunks = []; |
| | 229 | readStream.on('data', (chunk) => { |
| | 230 | chunks.push(chunk); |
| | 231 | }); |
| | 232 | |
| | 233 | readStream.on('end', () => { |
| | 234 | const buffer = Buffer.concat(chunks); |
| | 235 | resolve(buffer); |
| | 236 | zipfile.readEntry(); // Continue to the next entry |
| | 237 | }); |
| 225 | | 238 | |
| 226 | readStream.on('end', () => { | 239 | readStream.on('error', (err) => { |
| 227 | const buffer = Buffer.concat(chunks); | 240 | console.warn(`Error reading stream: ${err.message}`); |
| 228 | resolve(buffer); | 241 | zipfile.readEntry(); |
| 229 | zipfile.readEntry(); // Continue to the next entry | 242 | }); |
| | 243 | } |
| 230 | }); | 244 | }); |
| | 245 | } else { |
| | 246 | zipfile.readEntry(); |
| 231 | } | 247 | } |
| 232 | }); | 248 | }); |
| 233 | } else { | 249 | |
| 234 | zipfile.readEntry(); | 250 | zipfile.on('error', (err) => { |
| 235 | } | 251 | console.warn('ZIP processing error', err); |
| 236 | }); | 252 | resolve(null); |
| 237 | zipfile.on('end', () => resolve(null)); | 253 | }); |
| 238 | })); | 254 | |
| | 255 | zipfile.on('end', () => resolve(null)); |
| | 256 | }); |
| | 257 | } catch (error) { |
| | 258 | console.warn('Failed to process ZIP buffer', error); |
| | 259 | resolve(null); |
| | 260 | } |
| | 261 | }); |
| 239 | } | 262 | } |
| 240 | | 263 | |
| 241 | /** | 264 | /** |