ZIP extraction error handling (#4002) * Improve error handling in extractFileFromZipBuffer function * Add warning logging to NovelAI image upscaling

c218c1baeaa58025ce38f1abc0dec742b0156097

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +30 -6Showing whitespace changes
src/endpoints/novelai.js+3 -2
@@ -394,7 +394,8 @@ router.post('/generate-image', async (request, response) => {
394 });394 });
395395
396 if (!upscaleResult.ok) {396 if (!upscaleResult.ok) {
397 throw new Error('NovelAI returned an error.');397 const text = await upscaleResult.text();
398 throw new Error('NovelAI returned an error.', { cause: text });
398 }399 }
399400
400 const upscaledArchiveBuffer = await upscaleResult.arrayBuffer();401 const upscaledArchiveBuffer = await upscaleResult.arrayBuffer();
@@ -408,7 +409,7 @@ router.post('/generate-image', async (request, response) => {
408409
409 return response.send(upscaledBase64);410 return response.send(upscaledBase64);
410 } catch (error) {411 } catch (error) {
411 console.warn('NovelAI generated an image, but upscaling failed. Returning original image.');412 console.warn('NovelAI generated an image, but upscaling failed. Returning original image.', error);
412 return response.send(originalBase64);413 return response.send(originalBase64);
413 }414 }
414 } catch (error) {415 } catch (error) {
src/util.js+27 -4
@@ -207,16 +207,23 @@ export function formatBytes(bytes) {
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 */
209export async function extractFileFromZipBuffer(archiveBuffer, fileExtension) {209export 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 yauzl.fromBuffer(Buffer.from(archiveBuffer), { lazyEntries: true }, (err, zipfile) => {
213 if (err) {
214 console.warn(`Error opening ZIP file: ${err.message}`);
215 return resolve(null);
216 }
212217
213 zipfile.readEntry();218 zipfile.readEntry();
219
214 zipfile.on('entry', (entry) => {220 zipfile.on('entry', (entry) => {
215 if (entry.fileName.endsWith(fileExtension) && !entry.fileName.startsWith('__MACOSX')) {221 if (entry.fileName.endsWith(fileExtension) && !entry.fileName.startsWith('__MACOSX')) {
216 console.info(`Extracting ${entry.fileName}`);222 console.info(`Extracting ${entry.fileName}`);
217 zipfile.openReadStream(entry, (err, readStream) => {223 zipfile.openReadStream(entry, (err, readStream) => {
218 if (err) {224 if (err) {
219 reject(err);225 console.warn(`Error opening read stream: ${err.message}`);
226 return zipfile.readEntry();
220 } else {227 } else {
221 const chunks = [];228 const chunks = [];
222 readStream.on('data', (chunk) => {229 readStream.on('data', (chunk) => {
@@ -228,14 +235,30 @@ export async function extractFileFromZipBuffer(archiveBuffer, fileExtension) {
228 resolve(buffer);235 resolve(buffer);
229 zipfile.readEntry(); // Continue to the next entry236 zipfile.readEntry(); // Continue to the next entry
230 });237 });
238
239 readStream.on('error', (err) => {
240 console.warn(`Error reading stream: ${err.message}`);
241 zipfile.readEntry();
242 });
231 }243 }
232 });244 });
233 } else {245 } else {
234 zipfile.readEntry();246 zipfile.readEntry();
235 }247 }
236 });248 });
249
250 zipfile.on('error', (err) => {
251 console.warn('ZIP processing error', err);
252 resolve(null);
253 });
254
237 zipfile.on('end', () => resolve(null));255 zipfile.on('end', () => resolve(null));
238 }));256 });
257 } catch (error) {
258 console.warn('Failed to process ZIP buffer', error);
259 resolve(null);
260 }
261 });
239}262}
240263
241/**264/**