@@ -6,7 +6,6 @@ import archiver from 'archiver'
66import type { Context } from 'hono'
77import { stream } from 'hono/streaming'
88import mime from 'mime'
9- import { Readable } from 'node:stream'
109import { z } from 'zod'
1110import prisma from '../../prisma.js'
1211import { openFileStream } from '../../services/file/helpers/getFileUrl.js'
@@ -119,54 +118,67 @@ export async function veranstaltungPhotoArchive(ctx: Context<{ Variables: Author
119118
120119 const zip = archiver ( 'zip' )
121120
122- zip . on ( 'warning' , function ( err ) {
123- if ( err . code === 'ENOENT' ) {
124- console . warn ( err )
125- } else {
126- throw err
127- }
128- } )
129-
130- zip . on ( 'error' , function ( err ) {
131- throw err
132- } )
133-
134121 ctx . status ( 201 )
135122 ctx . header ( 'Content-Type' , 'application/zip' )
136123 ctx . header ( 'Content-Disposition' , `attachment; filename="${ mode === 'flat' ? 'FotosForAutomation' : 'Fotos' } .zip"` )
137124
138125 zip . append ( `Gesamtzahl Fotos: ${ anmeldungen . length } ` , { name : `${ baseDirectory } /README.txt` } )
139126
140- for ( const { person, unterveranstaltung } of anmeldungen ) {
141- if ( ! person . photo ) {
142- continue
143- }
127+ return stream ( ctx , async ( s ) => {
128+ zip . on ( 'data' , ( chunk ) => {
129+ /* eslint-disable @typescript-eslint/no-floating-promises */
130+ s . write ( chunk )
131+ } )
144132
145- const stream = await openFileStream ( person . photo )
133+ for ( const { person, unterveranstaltung } of anmeldungen ) {
134+ if ( ! person . photo ) {
135+ continue
136+ }
146137
147- const directory = `${ unterveranstaltung . veranstaltung . name } /${ unterveranstaltung . gliederung . name } `
148- const basename = mode === 'group' ? `${ person . firstname } ${ person . lastname } ` : person . id
149- const extension = mime . getExtension ( person . photo . mimetype ?? 'text/plain' )
138+ const stream = await openFileStream ( person . photo )
150139
151- zip . append ( stream , {
152- name :
153- mode === 'group'
154- ? `${ baseDirectory } /${ directory } /${ basename } .${ extension } `
155- : `Fotos/${ person . photo . id } .${ extension } ` ,
156- date : person . photo . createdAt ,
157- } )
158- }
140+ stream . on ( 'end' , ( ) => {
141+ stream . destroy ( )
142+ } )
159143
160- if ( mode === 'flat' ) {
161- const buffer = buildSheet ( anmeldungen , account . person )
162- zip . append ( buffer , {
163- name : 'Datenzusammenführung.xlsx' ,
164- } )
165- }
144+ const directory = `${ unterveranstaltung . veranstaltung . name } /${ unterveranstaltung . gliederung . name } `
145+ const basename = mode === 'group' ? `${ person . firstname } ${ person . lastname } ` : person . id
146+ const extension = mime . getExtension ( person . photo . mimetype ?? 'text/plain' )
147+
148+ zip . append ( stream , {
149+ name :
150+ mode === 'group'
151+ ? `${ baseDirectory } /${ directory } /${ basename } .${ extension } `
152+ : `Fotos/${ person . photo . id } .${ extension } ` ,
153+ date : person . photo . createdAt ,
154+ } )
155+ }
166156
167- await zip . finalize ( )
157+ if ( mode === 'flat' ) {
158+ const buffer = buildSheet ( anmeldungen , account . person )
159+ zip . append ( buffer , {
160+ name : 'Datenzusammenführung.xlsx' ,
161+ } )
162+ }
168163
169- return stream ( ctx , async ( s ) => {
170- await s . pipe ( Readable . toWeb ( zip ) )
164+ /* eslint-disable @typescript-eslint/no-floating-promises */
165+ zip . finalize ( )
166+
167+ await new Promise < void > ( ( resolve , reject ) => {
168+ zip . on ( 'warning' , function ( err ) {
169+ if ( err . code === 'ENOENT' ) {
170+ console . warn ( err )
171+ } else {
172+ reject ( err )
173+ }
174+ } )
175+
176+ zip . once ( 'end' , ( ) => {
177+ resolve ( )
178+ } )
179+ zip . once ( 'error' , ( err ) => {
180+ reject ( err )
181+ } )
182+ } )
171183 } )
172184}
0 commit comments