package Ġru . s ui . su ib ack end . controller Ċ Ċ import Ġcom . fasterxml . jackson . databind . ObjectMapper Ċ import Ġcom . google . common . cache . Cache Builder Ċ import Ġorg . apache . poi . ss . user model . Cell Type Ċ import Ġorg . apache . poi . ss . user model . Row Ċ import Ġorg . apache . poi . ss . user model . Sheet Ċ import Ġorg . apache . poi . ss . user model . Workbook Factory Ċ import Ġorg . apache . poi . x ss f . streaming . SX SS F Workbook Ċ import Ġorg . apache . poi . x ss f . user model . XSS F Workbook Ċ import Ġorg . springframework . context . ApplicationContext Ċ import Ġorg . springframework . http . MediaType Ċ import Ġorg . springframework . web . bind . annotation .* Ċ import Ġorg . springframework . web . multipart . Multipart File Ċ import Ġorg . springframework . web . socket . WebSocket Session Ċ import Ġorg . springframework . web . socket . messaging . Sub Protocol WebSocket Handler Ċ import Ġru . s ui . su ib ack end . model . User State Ċ import Ġru . s ui . su ib ack end . service . Backend Service Ċ import Ġru . s ui . su ib ack end . utils . Constants . BACKEND _ ENDPOINT Ċ import Ġru . s ui . su ib ack end . utils . Constants . INIT _ SESSION _ ID _ KEY Ċ import Ġjava . io . File Ċ import Ġjava . io . InputStream Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . zip . Zip Entry Ċ import Ġjava . util . zip . Zip InputStream Ċ import Ġjava . util . zip . Zip OutputStream Ċ import Ġjavax . servlet . http . HttpServletResponse Ċ import Ġjavax . validation . constraints . Max Ċ import Ġjavax . validation . constraints . Min Ċ import Ġkotlin . reflect . K Property 1 Ċ import Ġkotlin . reflect . full . declared Member Properties Ċ import Ġkotlin . reflect . jvm . is Accessible ĊĊ Ċ private Ġconst Ġval ĠNO _ C ACHED _ SESSION _ ERROR _ MESSAGE Ġ= Ġ" Please Ġcall Ġ/ init Ġmethod Ġfirst " Ċ private Ġconst Ġval ĠMAX _ DB _ FETCH _ SIZE Ġ= Ġ 5 0 _ 0 0 0 L Ċ private Ġconst Ġval ĠMAX _ ROWS _ PER _ SHE ET Ġ= Ġ 2 5 0 _ 0 0 0 Ċ Ċ private Ġfun ĠZip InputStream . to File Iterator (): ĠIterator < Pair < String , ĠInputStream >> Ġ{ ĊĠĠĠ Ġval Ġzip InputStream Ġ= Ġthis ĊĊĠĠĠ Ġreturn Ġiterator Ġ{ ĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġzip InputStream . next Entry ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . isDirectory ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( entry . name . endsWith (". zip ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠZip InputStream ( zip InputStream ). to File Iterator (). forEach Ġ{ Ġyield ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġyield ( entry . name Ġto Ġzip InputStream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun ĠSheet . put Row ( row Number : ĠInt , Ġrow : ĠRow ) Ġ{ ĊĠĠĠ Ġval Ġsheet Row Ġ= Ġthis . create Row ( row Number ) ĊĠĠĠ Ġrow . forEach Ġ{ Ġcell Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġsheet Cell Ġ= Ġsheet Row . create Cell ( cell . column Index , Ġcell . cell Type ) ĊĊĠĠĠĠĠĠĠ Ġsheet Cell . cell Style Ġ= Ġcell . cell Style ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( cell . cell Type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . NUMERIC Ġ-> Ġsheet Cell . setCellValue ( cell . numeric CellValue ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . STRING Ġ-> Ġsheet Cell . setCellValue ( cell . string CellValue ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . FORM ULA Ġ-> Ġsheet Cell . cell Formula Ġ= Ġcell . cell Formula ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . BLANK Ġ-> Ġsheet Cell . setCellValue ( cell . string CellValue ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . BOOLEAN Ġ-> Ġsheet Cell . setCellValue ( cell . boolean CellValue ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCell Type . ERROR Ġ-> Ġsheet Cell . set Cell Error Value ( cell . error CellValue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Unsupported Ġcell Ġtype : Ġ${ cell . cell Type }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ RestController Ċ @ RequestMapping ("$ BACKEND _ ENDPOINT / export ") Ċ @ Cross Origin Ċ class ĠExport Controller ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠobjectMapper : ĠObjectMapper , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbackend Service : ĠBackend Service , ĊĠĠĠĠĠĠĠ Ġ// ĠÐŁ Ð¾Ð» ÑĥÑĩ ÐµÐ½Ð¸Ðµ Ġuser State ĠÐ¿Ð¾ Ġid ĠÑģ ÐµÑģ Ñģ Ð¸Ð¸ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġhttp Controller : ĠHttp Controller , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġapplication Context : ĠApplication Context Ċ ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġexport Info Cache Ġ= ĠCache Builder ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. expire After Write ( 1 2 , ĠTimeUnit . HOUR S ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build < String , ĠExport Info >() ĊĊĠĠĠ Ġ@ PostMapping ("/ init ") ĊĠĠĠ Ġfun Ġinit (@ Request Header ( INIT _ SESSION _ ID _ KEY ) ĠsessionId : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuser State Ġ= Ġhttp Controller . user State Cache . get If Present ( sessionId ) Ġ?: ĠgetUser State From WebSocket Session ( sessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( user State Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser State For Export Ġ= Ġuser State . copy (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . offset Ġ= Ġ 0 L ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . group ings Ġ= Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . expanded Groups Ġ= Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġexport Info Cache . put ( sessionId , ĠExport Info ( user State For Export )) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" Couldn 't Ġfind Ġsession Ġwith Ġid Ġ= Ġ$ sessionId ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠ Ġprivate Ġfun ĠgetUser State From WebSocket Session ( sessionId : ĠString ): ĠUser State ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsessions Ġ= ĠSub Protocol WebSocket Handler :: class . declared Member Properties ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first Ġ{ Ġit . name Ġ== Ġ" sessions " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Ġ{ Ġthis . is Accessible Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. get ( application Context . getBean ( Sub Protocol WebSocket Handler :: class . java )) Ġas ĠMap < String , ĠAny > ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsessions ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġ( id , Ġsession Holder ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsession Ġ= Ġ( session Holder ):: class . declared Member Properties ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first Ġ{ Ġit . name Ġ== Ġ" session " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. let Ġ{ Ġit Ġas ĠK Property 1 < Any , ĠWebSocket Session > Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Ġ{ Ġthis . is Accessible Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. get ( session Holder ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinit SessionId Ġ= Ġ( session . attributes [ INIT _ SESSION _ ID _ KEY ] Ġas ĠString ?) Ġ?: Ġid ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ map Ġinit SessionId Ġto Ġsession ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull Ġ{ Ġit . first Ġ== ĠsessionId Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . second ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . attributes ?. get (" state ") Ġas ĠUser State ? ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ GetMapping ("/ data ") ĊĠĠĠ Ġfun Ġraw Data ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Request Header ( INIT _ SESSION _ ID _ KEY ) ĠsessionId : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ RequestParam (" file Count ") Ġ@ Min ( 1 ) Ġfile Count : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ RequestParam (" file Size ") Ġ@ Min ( 1 ) Ġ@ Max ( MAX _ DB _ FETCH _ SIZE ) ĠfileSize : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresponse : ĠHttpServletResponse ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuser State Ġ= Ġexport Info Cache . get If Present ( sessionId )?. user State Ġ?: Ġerror ( NO _ C ACHED _ SESSION _ ERROR _ MESSAGE ) ĊĊĠĠĠĠĠĠĠ Ġresponse . contentType Ġ= ĠMediaType . APPLICATION _ JSON _ VALUE ĊĊĠĠĠĠĠĠĠ ĠZip OutputStream ( response . output Stream ). use Ġ{ Ġzip OutputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠobjectMapper . writer (). write Values ( zip OutputStream ). use Ġ{ Ġwriter Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġpart Number Ġ= Ġ 1 ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( chunk Ġin Ġ( 1 .. file Count ). chunk ed (( MAX _ DB _ FETCH _ SIZE Ġ/ ĠfileSize ). toInt ())) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuser State . pageSize Ġ= Ġ( chunk . size Ġ* ĠfileSize ). to Long () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpage Data Ġ= Ġbackend Service . getData ( user State ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Data . total Count Ġ> Ġuser State . offset ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpage Data . data ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. chunk ed ( file Size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip OutputStream . put Next Entry ( Zip Entry ("${ part Number ++ }. json ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip OutputStream . close Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuser State . offset Ġ+= Ġuser State . pageSize ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Data . total Count Ġ<= Ġuser State . offset ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ PostMapping ("/ import Parts ") ĊĠĠĠ Ġfun Ġimport Parts (@ Request Header ( INIT _ SESSION _ ID _ KEY ) ĠsessionId : ĠString , Ġfile : ĠMultip art File ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġexport Info Ġ= Ġexport Info Cache . get If Present ( sessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( export Info Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠZip InputStream ( file . inputStream ). use Ġ{ Ġzip InputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠÐł Ð°Ñģ Ðº Ð» Ð°Ð´ ÑĭÐ² Ð°ÐµÑĤ ĠÑĦÐ°Ð¹Ð» Ñĭ ĠÐ¿Ð¾ ĠÐ¾ÑĤ Ð´ ÐµÐ»ÑĮ Ð½ÑĭÐ¼ Ġzip ĠÐ´Ð»Ñı ĠÐ²Ð¾Ð· Ð¼Ð¾Ð¶ Ð½Ð¾ÑģÑĤÐ¸ ĠÐ·Ð°Ðº ÑĢÑĭ ÑĤÐ¸ Ñı ĠÐ² Ð¾ÑĢ Ðº Ð± Ñĥ ÐºÐ¾Ð² ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip InputStream . to File Iterator (). forEach Ġ{ Ġ(_, ĠinputStream ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocal File Ġ= ĠFile ("/ tmp / backend - export /${ UUID . randomUUID ()}. zip "). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . parent File . mkdir s () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . createNew File () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . delete On Exit () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠZip OutputStream ( local File . output Stream ()). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . put Next Entry ( Zip Entry (" part . xlsx ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠinputStream . copy To ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . close Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexport Info . parts . add ( local File ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerror ( NO _ C ACHED _ SESSION _ ERROR _ MESSAGE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ GetMapping ("/ join Parts ") ĊĠĠĠ Ġfun Ġjoin Parts (@ Request Header ( INIT _ SESSION _ ID _ KEY ) ĠsessionId : ĠString , Ġresponse : ĠHttpServletResponse ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġexport Info Ġ= Ġexport Info Cache . get If Present ( sessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( export Info Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrow Iterator Ġ= Ġiterator Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexport Info . parts . forEach Indexed Ġ{ Ġpart Index , Ġpart Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠZip InputStream ( part . inputStream ()). use Ġ{ Ġzip InputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠÐĲ ÑĢ Ñħ Ð¸Ð² ĠÑģ Ð¾Ð´ÐµÑĢÐ¶ Ð¸ÑĤ ĠÑĤÐ¾Ð»ÑĮÐºÐ¾ Ġ 1 Ġx ls x Ġ( Ñĩ ÑĤÐ¾Ð±Ñĭ ĠÐ¼Ð¾Ð¶Ð½Ð¾ ĠÐ±Ñĭ Ð»Ð¾ ĠÐ·Ð°Ðº ÑĢÑĭ ÑĤÑĮ ĠÐ² Ð¾ÑĢ Ðº Ð± Ñĥ Ðº ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( zip InputStream . next Entry Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠWork book Factory . create ( zip InputStream ). use Ġ{ Ġworkbook Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġworkbook . sheet Iterator () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġit . row Iterator (). as Sequence () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. let Ġ{ Ġif Ġ( part Index Ġ!= Ġ 0 ) Ġit . drop ( 1 ) Ġelse Ġit Ġ} Ġ// ĠSkip Ġheader Ġfor Ġ 2 + Ġfiles ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġyield ( it ) Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip InputStream . close Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . contentType Ġ= Ġ" application / vnd . open xm lform ats - off iced ocument . spreadsheet ml . sheet " ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSX SS F Workbook ( XSS F Workbook ()). use Ġ{ Ġworkbook Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( row Iterator . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġheader Row Ġ= Ġrow Iterator . next () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsheet : ĠSheet ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow Iterator . as Sequence (). forEach Indexed Ġ{ ĠrowIndex , Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsheet RowIndex Ġ= ĠrowIndex Ġ% ĠMAX _ ROWS _ PER _ SHE ET ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( sheet RowIndex Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsheet Ġ= Ġworkbook . create Sheet (( rowIndex Ġ/ ĠMAX _ ROWS _ PER _ SHE ET Ġ+ Ġ 1 ). toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsheet !!. put Row ( 0 , Ġheader Row ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsheet !!. put Row ( sheet RowIndex Ġ+ Ġ 1 , Ġrow ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠZip OutputStream ( response . output Stream ). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . put Next Entry ( Zip Entry (" table . xlsx ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġworkbook . write ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . close Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexport Info . parts . forEach Ġ{ Ġkotlin . run Catch ing Ġ{ Ġit . delete () Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexport Info Cache . invalidate ( sessionId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerror ( NO _ C ACHED _ SESSION _ ERROR _ MESSAGE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ } Ċ Ċ private Ġclass ĠExport Info ( ĊĠĠĠĠĠĠĠ Ġval Ġuser State : ĠUser State , ĊĠĠĠĠĠĠĠ Ġval Ġparts : ĠMutable List < File > Ġ= Ġmutable ListOf () Ċ ) Ċ