1. 概要
前回はスマホからローカル環境にアクセスする内容についてでした。今回はPDFを表示&ダウンロードする内容になります。
対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。
2. nodeのインストール
こちらを参考
3. プロジェクトを作成
3-1-1. こちらを参考
4. 必要なライブラリをインストール
4-1-1. こちらを参考
npm install @react-pdf/renderer --save
4-1-2. Requirements
You should upgrade to Next.js 14.1.1 or later.
- React-pdf
- Compatibility with Next.js
5. ソースコード
※前回より差分のみを記載
5-1-1. src/app/components/component11/my-document.tsx
import { Document, Page, StyleSheet, View, Text } from "@react-pdf/renderer";
const styles = StyleSheet.create({
page: {
flexDirection: "row",
backgroundColor: "#E4E4E4",
},
section: {
margin: 10,
padding: 10,
flexGrow: 1,
},
});
const MyDocument = () => {
return (
<Document>
<Page size={"A4"} style={styles.page}>
<View style={styles.section}>
<Text>Section #1</Text>
</View>
<View style={styles.section}>
<Text>Section #2</Text>
</View>
</Page>
</Document>
);
};
export default MyDocument;5-1-2. src/app/components/component11/view-pdf.tsx
import { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import Modal from "@mui/material/Modal";
import { PDFViewer } from "@react-pdf/renderer";
import MyDocument from "./my-document";
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "80vh",
height: "60vh",
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
};
type Props = {
name: string;
open: boolean;
setOpen: Function;
};
const ViewPDF = (props: Props) => {
const [loaded, setLoaded] = useState<boolean>(false);
useEffect(() => {
setLoaded(true);
}, []);
const handleClose = () => props.setOpen(false);
return (
<div style={{ height: "100vh" }}>
<Modal
open={props.open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
{loaded && (
<PDFViewer showToolbar={true} width={"100%"} height={"100%"}>
<MyDocument />
</PDFViewer>
)}
</Box>
</Modal>
</div>
);
};
export default ViewPDF;5-1-3. src/app/components/component11/download-pdf.tsx
import { useEffect, useState } from "react";
import Button from "@mui/material/Button";
import { PDFDownloadLink } from "@react-pdf/renderer";
import MyDocument from "./my-document";
type Props = {
fileName: string;
};
const DownloadPDF = (props: Props) => {
const [loaded, setLoaded] = useState<boolean>(false);
useEffect(() => {
setLoaded(true);
}, []);
return (
<div>
{loaded && (
<PDFDownloadLink document={<MyDocument />} fileName={props.fileName}>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<Button variant={"contained"} sx={{ width: 200 }}>
Download PDF
</Button>
)
}
</PDFDownloadLink>
)}
</div>
);
};
export default DownloadPDF;5-1-4. src/app/components/component11/client-page.tsx
"use client";
import { useState } from "react";
import { Button, Stack } from "@mui/material";
import ViewPDF from "./view-pdf";
import DownloadPDF from "./download-pdf";
const ClientPage = () => {
const [open, setOpen] = useState(false);
return (
<>
<Stack spacing={2} direction={"column"} textAlign={"center"}>
<div>
<Button
variant={"contained"}
sx={{ width: 200 }}
onClick={() => setOpen(true)}
>
View PDF
</Button>
</div>
<DownloadPDF fileName={"somename.pdf"} />
</Stack>
<ViewPDF name={"pdf"} open={open} setOpen={setOpen} />
</>
);
};
export default ClientPage;5-1-5. src/app/components/component11/page.module.scss
.component {
& ul {
margin-left: 20px;
& li {
list-style: disc;
}
}
& .calendar_area {
text-align: center;
}
}5-1-6. src/app/components/component11/page.tsx
import Divider from "@mui/material/Divider";
import GoBack from "@/lib/components/go-back";
import scss from "./page.module.scss";
import ClientPage from "./client-page";
const Component11 = () => {
return (
<div className={scss.component}>
<GoBack />
<br />
<br />
<ul>
<li>PDF</li>
<ul>
<li>表示</li>
<li>生成</li>
</ul>
</ul>
<Divider sx={{ marginTop: 2, marginBottom: 2 }} />
<div className={scss.calendar_area}>
<ClientPage />
</div>
</div>
);
};
export default Component11;5-1-7. src/app/components/page.module.scss
.components {
color: blue;
& ul {
margin-left: 20px;
& li {
list-style: disc;
}
}
}5-1-8. src/app/components/page.tsx
"use client";
import React from "react";
import { Link } from "@mui/material";
import scss from "./page.module.scss";
const Components = () => {
return (
<div className={scss.components}>
<ul>
<li>
<Link href="/components/component01" underline="hover">
Component01
</Link>
</li>
<li>
<Link href="/components/component02" underline="hover">
Component02
</Link>
</li>
<li>
<Link href="/components/component03" underline="hover">
Component03
</Link>
</li>
<li>
<Link href="/components/component04" underline="hover">
Component04
</Link>
</li>
<li>
<Link href="/components/component05" underline="hover">
Component05
</Link>
</li>
<li>
<Link href="/components/component06" underline="hover">
Component06
</Link>
</li>
<li>
<Link href="/components/component07" underline="hover">
Component07
</Link>
</li>
<li>
<Link href="/components/component08" underline="hover">
Component08
</Link>
</li>
<li>
<Link href="/components/component09" underline="hover">
Component09
</Link>
</li>
<li>
<Link href="/components/component10" underline="hover">
Component10
</Link>
</li>
<li>
<Link href="/components/component11" underline="hover">
Component11
</Link>
</li>
</ul>
</div>
);
};
export default Components;6. サーバーを起動
npm run dev
7. ブラウザで確認
- http://localhost:3000
7-1-1. 表示


7-2-1. ダウンロード


8. ディレクトリの構造
省略9. 備考
今回はPDFを表示&ダウンロードする内容についてでした。
10. 参考
- Docs | Next.js (nextjs.org)
- Quick Start – React
- Getting Started with Redux | Redux
- Getting Started with React Redux | React Redux (react-redux.js.org)
- Material UI: React components based on Material Design (mui.com)
- React-pdf
- jspdf vs react-pdf vs pdf-lib vs pdfmake vs pdfkit vs @react-pdf/renderer | “PDF生成ライブラリ” npm パッケージ比較
投稿者プロフィール
-
開発好きなシステムエンジニアです。
卓球にハマってます。






















