boardService->getBoardBySlug($slug); $validated = $request->validated(); // post_id가 없으면 임시 업로드 (temp_key 필수) $postId = $validated['post_id'] ?? null; $tempKey = $validated['temp_key'] ?? null; $attachment = $this->attachmentService->upload( slug: $slug, file: $request->file('file'), postId: $postId, collection: $validated['collection'] ?? 'attachments', tempKey: $tempKey ); // FileUploader 컴포넌트가 response.data?.data 형식을 기대하므로 // data 키 안에 한 번 더 감싸서 반환 return $this->success( 'sirsoft-board::messages.attachment.upload_success', [ 'data' => [ 'id' => $attachment->id, 'hash' => $attachment->hash, 'original_filename' => $attachment->original_filename, 'stored_filename' => $attachment->stored_filename, 'mime_type' => $attachment->mime_type, 'size' => $attachment->size, 'url' => $this->attachmentService->getUrl($slug, $attachment->id), 'order' => $attachment->order, 'created_at' => $attachment->created_at, ], ], 201 ); } catch (AttachmentLimitExceededException $e) { // 게시판 첨부 개수 상한 초과 — generic 500 이 아닌 422 명시 차단 return $this->error( $e->getMessageKey(), 422, ['code' => 'attachment_limit_exceeded'], $e->getMessageParams() ); } catch (BoardNotFoundException $e) { return $this->error('sirsoft-board::messages.boards.not_found', 404); } catch (\Exception $e) { return $this->error('sirsoft-board::messages.attachment.upload_failed', 500, $e->getMessage()); } } /** * 첨부파일 삭제 * * @param string $slug 게시판 슬러그 * @param int $id 첨부파일 ID * @return JsonResponse 삭제 결과 응답 */ public function destroy(string $slug, int $id): JsonResponse { try { // 게시판 존재 여부 확인 $this->boardService->getBoardBySlug($slug); // 첨부파일 조회 (Service를 통해) $attachment = $this->attachmentService->getById($slug, $id); if (! $attachment) { return $this->error('sirsoft-board::messages.attachment.not_found', 404); } // 삭제 (Service에서 처리) $result = $this->attachmentService->delete($slug, $id, 'admin'); if (! $result) { return $this->error('sirsoft-board::messages.attachment.delete_failed', 500); } return $this->success('sirsoft-board::messages.attachment.delete_success'); } catch (BoardNotFoundException $e) { return $this->error('sirsoft-board::messages.boards.not_found', 404); } catch (\Exception $e) { return $this->error('sirsoft-board::messages.attachment.delete_failed', 500, $e->getMessage()); } } /** * 첨부파일 순서 변경 * * @param ReorderAttachmentsRequest $request 순서 변경 요청 * @param string $slug 게시판 슬러그 * @return JsonResponse 순서 변경 결과 응답 */ public function reorder(ReorderAttachmentsRequest $request, string $slug): JsonResponse { try { // 게시판 존재 여부 확인 $this->boardService->getBoardBySlug($slug); $validated = $request->validated(); // FileUploader가 [{id, order}] 형태로 전송 → [ID => order] 매핑으로 변환 $orders = collect($validated['order'])->pluck('order', 'id')->all(); $result = $this->attachmentService->reorder($slug, $orders, 'admin'); if (! $result) { return $this->error('sirsoft-board::messages.attachment.reorder_failed', 500); } return $this->success('sirsoft-board::messages.attachment.reorder_success'); } catch (BoardNotFoundException $e) { return $this->error('sirsoft-board::messages.boards.not_found', 404); } catch (\Exception $e) { return $this->error('sirsoft-board::messages.attachment.reorder_failed', 500, $e->getMessage()); } } /** * 첨부파일 다운로드 (해시 기반) * * @param string $slug 게시판 슬러그 * @param string $hash 첨부파일 해시 * @return StreamedResponse|JsonResponse 파일 스트림 또는 오류 응답 */ public function download(string $slug, string $hash): StreamedResponse|JsonResponse { try { // 게시판 존재 여부 확인 $this->boardService->getBoardBySlug($slug); // 해시로 첨부파일 조회 $attachment = $this->attachmentService->getByHash($slug, $hash); if (! $attachment) { return $this->error('sirsoft-board::messages.attachment.not_found', 404); } // 다운로드 응답 생성 $response = $this->attachmentService->download($slug, $attachment->id); if (! $response) { return $this->error('sirsoft-board::messages.attachment.file_not_found', 404); } return $response; } catch (AccessDeniedHttpException $e) { return $this->error('auth.scope_denied', 403); } catch (BoardNotFoundException $e) { return $this->error('sirsoft-board::messages.boards.not_found', 404); } catch (\Exception $e) { return $this->error('sirsoft-board::messages.attachment.download_failed', 500, $e->getMessage()); } } }