From 52a2032a8c5061c3a6590b9f1fcefd3779d1d571 Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 11:25:30 +0900 Subject: [PATCH] feat: implement file download function --- .env.development | 2 ++ .env.localhost | 1 + src/app/api/qna/file/route.ts | 17 ++++++++++++++--- src/app/api/qna/save/route.ts | 1 + src/components/inquiry/Answer.tsx | 10 ++++++++-- src/components/inquiry/Detail.tsx | 7 ++++++- src/components/inquiry/RegistForm.tsx | 19 +++++++++---------- src/hooks/useInquiry.ts | 22 ++++++++++++++++++---- 8 files changed, 59 insertions(+), 20 deletions(-) diff --git a/.env.development b/.env.development index 8e6fead..b446848 100644 --- a/.env.development +++ b/.env.development @@ -9,6 +9,8 @@ NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 +NEXT_PUBLIC_INQUIRY_FILE_DOWNLOAD_API_URL=https://jp-dev.qsalesplatform.com + #QPARTNER 로그인 api DB_HOST=202.218.61.226 diff --git a/.env.localhost b/.env.localhost index 29cb5c2..ba9def8 100644 --- a/.env.localhost +++ b/.env.localhost @@ -9,6 +9,7 @@ NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 +NEXT_PUBLIC_INQUIRY_FILE_DOWNLOAD_API_URL=https://jp-dev.qsalesplatform.com #QPARTNER 로그인 api DB_HOST=202.218.61.226 diff --git a/src/app/api/qna/file/route.ts b/src/app/api/qna/file/route.ts index a122da6..38aaf1b 100644 --- a/src/app/api/qna/file/route.ts +++ b/src/app/api/qna/file/route.ts @@ -4,19 +4,30 @@ import { NextResponse } from 'next/server' export async function GET(request: Request) { const { searchParams } = new URL(request.url) const encodeFileNo = searchParams.get('encodeFileNo') + const srcFileNm = searchParams.get('srcFileNm') if (!encodeFileNo) { return NextResponse.json({ error: 'encodeFileNo is required' }, { status: 400 }) } try { - const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/file/downloadFile`, { + const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_FILE_DOWNLOAD_API_URL}/api/file/downloadFile2`, { + responseType: 'arraybuffer', params: { encodeFileNo, }, }) - return NextResponse.json(response.data) + if (response.headers['content-type'] === 'application/octet-stream;charset=UTF-8') { + return new NextResponse(response.data, { + status: 200, + headers: { + 'Content-Type': 'application/octet-stream;charset=UTF-8', + 'Content-Disposition': `attachment; filename="${srcFileNm}"`, + }, + }) + } else { + return NextResponse.json({ error: 'file not found' }, { status: 404 }) + } } catch (error: any) { - console.error(error.response) return NextResponse.json({ error: error.response.data }, { status: 500 }) } } diff --git a/src/app/api/qna/save/route.ts b/src/app/api/qna/save/route.ts index f51ae66..b440ef8 100644 --- a/src/app/api/qna/save/route.ts +++ b/src/app/api/qna/save/route.ts @@ -3,6 +3,7 @@ import { NextResponse } from 'next/server' export async function POST(request: Request) { const formData = await request.formData() + console.log(formData) try { const response = await axios.post(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/qna/save`, formData, { headers: { diff --git a/src/components/inquiry/Answer.tsx b/src/components/inquiry/Answer.tsx index 76da68a..4df9c3b 100644 --- a/src/components/inquiry/Answer.tsx +++ b/src/components/inquiry/Answer.tsx @@ -2,7 +2,13 @@ import { Inquiry } from '@/types/Inquiry' -export default function Answer({ inquiryDetail, downloadFile }: { inquiryDetail: Inquiry; downloadFile: (encodeFileNo: number) => Promise }) { +export default function Answer({ + inquiryDetail, + downloadFile, +}: { + inquiryDetail: Inquiry + downloadFile: (encodeFileNo: number, srcFileNm: string) => Promise +}) { return ( <>
@@ -21,7 +27,7 @@ export default function Answer({ inquiryDetail, downloadFile }: { inquiryDetail:
    {inquiryDetail?.ansListFile?.map((file) => (
  • -
  • diff --git a/src/components/inquiry/Detail.tsx b/src/components/inquiry/Detail.tsx index 76ffaad..9e5d971 100644 --- a/src/components/inquiry/Detail.tsx +++ b/src/components/inquiry/Detail.tsx @@ -65,7 +65,12 @@ export default function Detail() {
      {inquiryDetail?.listFile?.map((file) => (
    • -
    • diff --git a/src/components/inquiry/RegistForm.tsx b/src/components/inquiry/RegistForm.tsx index 86d2ec9..0c3f452 100644 --- a/src/components/inquiry/RegistForm.tsx +++ b/src/components/inquiry/RegistForm.tsx @@ -74,7 +74,6 @@ export default function RegistForm() { focusOnRequiredField('qstMail') return } - const formData = new FormData() attachedFiles.forEach((file) => { formData.append('files', file) @@ -82,12 +81,6 @@ export default function RegistForm() { Object.entries(inquiryRequest).forEach(([key, value]) => { formData.append(key, value ?? '') }) - - const formDataObj: Record = {} - formData.forEach((value, key) => { - formDataObj[key] = value - }) - window.neoConfirm( 'お問い合わせを登録しますか? Hanwha Japanの担当者にお問い合わせメールが送信されます。', async () => { @@ -115,7 +108,9 @@ export default function RegistForm() { value={inquiryRequest.qnaClsLrgCd} onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsLrgCd: e.target.value })} > - + {commonCodeList .filter((code) => code.headCd === '204200') .map((code) => ( @@ -133,7 +128,9 @@ export default function RegistForm() { value={inquiryRequest.qnaClsMidCd} onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsMidCd: e.target.value })} > - + {commonCodeList .filter((code) => code.refChar1 === inquiryRequest.qnaClsLrgCd) .map((code) => ( @@ -151,7 +148,9 @@ export default function RegistForm() { value={inquiryRequest.qnaClsSmlCd ?? ''} onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsSmlCd: e.target.value })} > - + {commonCodeList .filter((code) => code.refChar1 === inquiryRequest.qnaClsMidCd) .map((code) => ( diff --git a/src/hooks/useInquiry.ts b/src/hooks/useInquiry.ts index 11c750a..a5ed2ab 100644 --- a/src/hooks/useInquiry.ts +++ b/src/hooks/useInquiry.ts @@ -15,7 +15,7 @@ export function useInquiry( isLoadingInquiryDetail: boolean isSavingInquiry: boolean saveInquiry: (formData: FormData) => Promise - downloadFile: (encodeFileNo: number) => Promise + downloadFile: (encodeFileNo: number, srcFileNm: string) => Promise commonCodeList: CommonCode[] } { const queryClient = useQueryClient() @@ -74,9 +74,23 @@ export function useInquiry( }, }) - const downloadFile = async (encodeFileNo: number) => { - const resp = await axiosInstance(null).get(`/api/qna/file`, { params: { encodeFileNo } }) - return resp.data + const downloadFile = async (encodeFileNo: number, srcFileNm: string) => { + try { + const resp = await axiosInstance(null).get(`/api/qna/file`, { params: { encodeFileNo, srcFileNm } }) + const blob = new Blob([resp.data], { type: 'application/octet-stream;charset=UTF-8' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `${srcFileNm}` + a.click() + URL.revokeObjectURL(url) + return blob + } catch (error: any) { + if (error.response.status === 404) { + alert('ファイルが見つかりません') + } + return null + } } const { data: commonCodeList, isLoading: isLoadingCommonCodeList } = useQuery({