web全栈框架next.js 使用api功能发送文件及多级路由

1,295 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

场景 在next中使用three.js 解析模型时 loader需要传入模型地址 但是next导入的模型文件直>接解析了 遂尝试 next的服务端功能 返回项目文件 在这里插入图片描述

一级

page/api/glb.ts

import type { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs";

/**
 * 返回模型文件 .glb
 */
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { name } = req.query;
  if (!name) res.status(500).send("未提供name字段");
  const filePath = path.resolve("./public/model", name as string);
  const stat = fs.statSync(filePath);

  res.writeHead(200, {
    "Content-Type": "application/octet-stream",
    "Content-Length": stat.size,
  });

  const readStream = fs.createReadStream(filePath);
  readStream.pipe(res);
}

参考 send-file-as-response-using-nextjs-api

还有另一种方法

/*
Project structure:
├── images_folder
│   └── next.jpg
├── package.json
├── pages
│   ├── api
│   │   └── image.js
│   └── index.js
├── README.md
└── yarn.lock
*/

// pages/api/image.js

import fs from 'fs'
import path from 'path'

const filePath = path.resolve('.', 'images_folder/next.jpg')
const imageBuffer = fs.readFileSync(filePath)

export default function(req, res) {
  res.setHeader('Content-Type', 'image/jpg')
  res.send(imageBuffer)
}

多级

page/api/draco/[name].ts

/*
 * @Author: hongbin
 * @Date: 2022-09-05 20:36:00
 * @LastEditors: hongbin
 * @LastEditTime: 2022-09-05 20:48:29
 * @Description: 返回 draco 文件 供解析glb模型使用
 */
import type { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs";

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const {
    query: { name },
  } = req;

  const filePath = path.resolve("./public/draco", name as string);
  const stat = fs.statSync(filePath);

  res.writeHead(200, {
    "Content-Type": "application/octet-stream",
    "Content-Length": stat.size,
  });

  const readStream = fs.createReadStream(filePath);
  readStream.pipe(res);
}

官方案例 在组件中使用useSWR发起请求

import type { User } from '../interfaces'
import useSwr from 'swr'
import Link from 'next/link'

const fetcher = (url: string) => fetch(url).then((res) => res.json())

export default function Index() {
  const { data, error } = useSwr<User[]>('/api/users', fetcher)

  if (error) return <div>Failed to load users</div>
  if (!data) return <div>Loading...</div>

  return (
    <ul>
      {data.map((user) => (
        <li key={user.id}>
          <Link href="/user/[id]" as={`/user/${user.id}`}>
            {`User ${user.id}`}
          </Link>
        </li>
      ))}
    </ul>
  )
}

发送数据

res.status(code)- 设置状态码的功能。code必须是有效的HTTP 状态码

res.json(body)- 发送 JSON 响应。body必须是可序列化的对象

res.send(body)- 发送 HTTP 响应。body可以是 a string, anobject或 aBuffer

res.redirect([status,] path)- 重定向到指定的路径或 URL。status必须是有效的HTTP 状态码。如果未指定,status默认为“307”“临时重定向”。