⭐前言
大家好,我是yma16,本文分享关于 vue3+threejs+koa可视化项目——模型文件上传(第四步)。
multipart切片上传
multipart content type 是指一种HTTP报文中的Content-Type的类型,它可以将一个HTTP请求或响应分为多个部分,每个部分可以有自己的Content-Type和内容。这种类型的报文通常用于传输多个文件或者消息体,每个部分可以有不同的编码方式和内容类型,比如图片、文本等不同的数据类型。
💖往期node系列文章
node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)
node实战——koa实现文件下载和图片/pdf/视频预览(node后端储备知识)
💖threejs系列相关文章
💖vue3+threejs系列
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
vue3+threejs可视化项目——引入threejs加载钢铁侠模型(第二步)
vue3+threejs+koa可视化项目——实现登录注册(第三步)
⭐koa后端文件上传(koa-body)
node 安装 koa-body
npm install koa-body
由于之前的博客是实现使用koa-bodyparser
需要卸载npm uninstall koa-bodyparser
引入koa-body
// 文件上传 app.use(koaBody({ multipart: true }))
💖自动创建目录
封装创建目录dirExists(不存在则创建)
const fs = require('fs'); const path = require('path'); /** * 读取路径信息 * @param {string} path 路径 */ function getStat(path) { return new Promise((resolve, reject) => { fs.stat(path, (err, stats) => { if (err) { resolve(false); } else { resolve(stats); } }) }) } /** * 创建路径 * @param {string} dir 路径 */ function mkdir(dir) { return new Promise((resolve, reject) => { fs.mkdir(dir, err => { if (err) { resolve(false); } else { resolve(true); } }) }) } /** * 路径是否存在,不存在则创建 * @param {string} dir 路径 */ async function dirExists(dir) { let isExists = await getStat(dir); //路径存在是目录 if (isExists && isExists.isDirectory()) { return true; } else if (isExists) { // 文件 return false; } //拿到上级路径 let tempDir = path.parse(dir).dir; //递归判断,如果上级目录也不存在,则会代码会在此处继续循环执行,直到目录存在 let status = await dirExists(tempDir); let mkdirStatus; if (status) { mkdirStatus = await mkdir(dir); } return mkdirStatus; } module.exports={ dirExists }
💖自定义目录上传
实现文件上传
const {dirExists} =require("../../utils/createDir"); const Router = require('koa-router'); const router = new Router(); const fs=require('fs') // 当前时间 const getCurrentTime=() =>{ const now = new Date() return `${now.valueOf()}` }; // upload file router.post('/upload/file', async (ctx) => { try{ // 获取上传的文件 const file = ctx.request.files.files; console.log('file',file) const dir='./db/file/'+getCurrentTime() await dirExists(dir); const file_path=`${dir}/${file.originalFilename}`; console.log('file_path',file_path) // 创建可读流 const reader = fs.createReadStream(file._writeStream.path); // 创建可写流 const upStream = fs.createWriteStream(file_path); // 可读流通过管道写入可写流 reader.pipe(upStream); ctx.body={ 'code':200, msg:'上传成功!' } } catch(e){ ctx.body = { code: 0, data:e, msg: 'upload media fail' }; } }); module.exports=router;
💖apifox自测上传接口
上传一张图片
上传成功!
⭐vue3前端上传模型文件
💖 axios 接口上传
http封装 上传配置content-type和token
// 实例 const createUploadInstance = (baseURL:string)=>{ //token const token = localStorage.getItem("userInfoPermissionToken") const Authorization = `bearer ${token}` return axios.create({ baseURL:baseURL, timeout: 1000000, headers: {"Content-Type": "multipart/form-data",Authorization} }) }; // @ts-ignore const uploadHttp:any=createUploadInstance('');
上传接口
// @ts-ignore import {uploadHttp} from "@/http/index"; export const uploadFile: any = (params: any) => { return uploadHttp.post("/api/upload/file", params); };
💖 使用 ant design vue 上传
上传页面
<template> <div> <div> 选择模型 </div> <a-upload-dragger name="file" :multiple="false" :file-list="state.fileList" :before-upload="beforeUpload" @remove="handleRemove" > <p class="ant-upload-drag-icon"> <inbox-outlined></inbox-outlined> </p> <p class="ant-upload-text">点击获取拖拽选择文件上传</p> </a-upload-dragger> <div style="margin-top: 20px;"> <a-button type="primary" @click="handleUpload"> 上传 </a-button> </div> </div> </template> <script lang="ts" setup> import { reactive } from 'vue'; import { InboxOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; import {uploadFile} from '@/service/upload/index' const state:any=reactive({ loading:false, fileList:[] }) const beforeUpload=(file:File)=>{ state.fileList=[file] return false; } const handleRemove = (file) => { state.fileList=[] }; const handleUpload = async () => { if(!state.fileList.length){ return message.warn('请选择文件') } const formData = new FormData(); state.fileList.forEach((file: any) => { formData.append('file', file as any); }); state.loading = true; try{ const res=await uploadFile(formData) console.log('res',res) } catch (e) { message.error(JSON.stringify(e)) } }; </script>
上传成功!
上传iron_man模型文件成功!
⭐总结
💖 后端koa
koa-body使用
koa-body是一个koa中间件,用于解析HTTP请求的body内容。它支持多种类型的body内容,包括json、form、text、multipart等。
使用koa-body的步骤如下:
- 安装koa-body模块:可以使用npm或者yarn进行安装。
npm install koa-body
- 引入koa-body模块:在koa的代码文件中,使用require语句引入koa-body。
const koaBody = require('koa-body');
- 注册koa-body中间件:在koa的代码文件中,使用app.use方法来注册koa-body中间件。
app.use(koaBody());
- 可以在传递koa-body的参数中指定解析body的类型和其他配置。例如,可以指定multipart的配置项如下:
app.use(koaBody({ multipart: true, formidable: { uploadDir: './uploads', keepExtensions: true, maxFileSize: 200 * 1024 * 1024 } }));
- 上述代码指定了将multipart类型的body解析为文件上传,并保存在"./uploads"目录下,同时限制了上传文件的大小为200MB。
- 在koa的路由处理函数中使用解析后的body内容:koa-body中间件会将解析后的body内容保存在ctx.request.body属性中,可以在koa的路由处理函数中通过ctx.request.body来使用解析后的body内容。
router.post('/', async (ctx) => { const requestBody = ctx.request.body; // ... });
可以根据具体的需求配置koa-body中间件,具体的配置项可以参考koa-body的文档。
💖 前端vue3
http封装
Axios是一个基于Promise的HTTP客户端库,可以用于浏览器和Node.js。它提供了一种简单、直观的方式来发送HTTP请求和处理响应。
为了更好地使用和管理Axios,可以对其进行封装。封装Axios可以使代码更加简洁、易于维护,并提供一些常用的功能,如错误处理、拦截请求和响应等。
以下是一个简单的Axios封装示例:
import axios from 'axios'; // 创建一个Axios实例 const instance = axios.create({ baseURL: 'http://api.example.com', // 设置请求的基础URL timeout: 5000 // 设置请求超时时间 }); // 请求拦截器 instance.interceptors.request.use( config => { // 在发送请求之前做些什么 return config; }, error => { // 对请求错误做些什么 return Promise.reject(error); } ); // 响应拦截器 instance.interceptors.response.use( response => { // 对响应数据做些什么 return response.data; }, error => { // 对响应错误做些什么 return Promise.reject(error); } ); export default instance;
在封装的Axios实例中,可以设置一些通用的配置,如基础URL和超时时间。还可以通过请求拦截器在发送请求之前做一些操作,如添加请求头,对请求参数进行处理等。类似地,通过响应拦截器可以对响应数据进行处理,如统一处理错误,转换响应数据等。
封装后的Axios实例可以通过导入的方式在其他地方使用,简化了代码的编写和维护。可以根据实际需求,进一步封装一些通用的API请求方法,以便在项目中重复使用。
总之,封装Axios可以提高开发效率,增强代码的可读性和可维护性,并提供一些常用的功能。
⭐结束
本文分享到这结束,如有错误或者不足之处欢迎指出!