环境搭建
准备工作
提示:本文采用ts来构建环境,要是以js构建则取掉类型定义即可。
初始化项目
创建目录
fileUpload-demo
- dist 编译后文件
- fileupload.html //上传文件静态页面
- src 存放源文件
- config.ts 配置文件
- handle-upload.ts 用户处理上传请求
- upload.ts 上传文件工具类
- app.ts 入口文件
- tsconfig.json ts编译配置
> npm init -y //初始化项目
安装相关依赖
npm i koa koa-router busboy qiniu --save
npm i typescript -D
npm install @types/koa @types/koa-router
代码实现
- 建立文件上传页面
目录: dist/fileupload.html
...省略
<form action="api/music/upload" method="POST" enctype="multipart/form-data">
<!-- input 中name 必须写... 不然busboy.on('file')无法监听 -->
<input type="file" name="file"/>
<input type="submit" value="submit"/>
</form>
- 文件入口页面
app.ts
import * as Koa from 'koa'
import * as Router from 'koa-router'
import * as fs from 'fs'
import { upload } from './src/handle_upload'
const app = new Koa();
const router = new Router();
router.get('/', async ctx => {
ctx.response.type = 'html'
ctx.body = await fs.readFileSync(__dirname + '/fileupload.html', 'utf-8');
});
router.post('/upload', async ctx => {
try {
const res = await upload(ctx);
ctx.body = { message: '上传成功', result: res };
} catch (error) {
ctx.body = { message: '上传失败', error };
}
})
app.use(router.routes())
.use(router.allowedMethods());
app.listen(3000, () => {
console.log('listen at port 3000');
})
- 处理上传文件请求
src/handle_upload.ts
import * as path from 'path'
import {uploadFile} from './upload'
/**
* 上传海报
*/
export const upload = async (ctx:any) => {
const serverPath = path.join(__dirname, '../uploadtemp/');
console.log(serverPath,'serverPath');
// 获取上传图片
const result:any = await uploadFile(ctx, {
fileType: 'poster',
path: serverPath
})
console.log(result,'图片信息');
const imgPath = path.join(serverPath, result.imgPath)
// 上传到七牛
const qiniu = await upToQiniu(imgPath, result.imgKey)
// 上传到七牛之后 删除原来的缓存文件
removeTemFile(imgPath)
return imgPath
}
- 配置文件
config.ts
const QINIU = {
accessKey: 'your_qn_accessKey',
secretKey: 'your_qn_secretKey',
bucket: 'naice',
origin: 'xxxxxx',
uploadURL: 'your_qn_uploadURL'
}
export {
QINIU
}
- 文件工具类
src/upload.ts- 处理文件上传服务
/**
* 同步创建文件目录
* @param {*} dirname 目录绝对地址
*/
const mkdirsSync = (dirname:string) => {
if (fs.existsSync(dirname)) {
return true
} else {
if (mkdirsSync(path.dirname(dirname))) {
fs.mkdirSync(dirname)
return true
}
}
return false;
}
//获取上传文件的后缀名
function getSuffix(fileName:string) {
return fileName.split('.').pop()
}
// 重命名
function Rename(fileName:string) {
return Math.random().toString(32).substr(4) + '.' + getSuffix(fileName)
}
// 删除文件
export const removeTemFile = (path:string) => {
fs.unlink(path, (err) => {
if (err) {
throw err
}
})
}
// 上传文件到服务
export const uploadFile = (ctx:any, options:any) => {
const busboy = new Busboy({ headers: ctx.req.headers });
//获取类型
const fileType = options.fileType || 'image'
const filePath = path.join(options.path, fileType)
const mkdirResult = mkdirsSync(filePath)
if (!mkdirResult) {
return
}
console.log('start uploading...')
return new Promise((resolve, reject)=> {
//解析文件请求事件
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
const fileName = Rename(filename)
const saveTo = path.join(path.join(filePath, fileName))
//文件保存到特定路径
file.pipe(fs.createWriteStream(saveTo))
//解析文件结束
file.on('end', function () {
resolve({
imgPath: `/${fileType}/${fileName}`,
imgKey: fileName
})
})
})
busboy.on('finish', function () {
console.log('finished...')
})
busboy.on('error', function (err:any) {
console.log('err...')
reject(err)
})
ctx.req.pipe(busboy)
})
}
- 添加七牛云上传方法
// 上传到七牛
export const upToQiniu = (filePath:string, key:string) => {
const accessKey = myConfig.QINIU.accessKey
const secretKey = myConfig.QINIU.secretKey
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
const options = {
scope: myConfig.QINIU.bucket
}
const putPolicy = new qiniu.rs.PutPolicy(options)
const uploadToken = putPolicy.uploadToken(mac)
const config:any= new qiniu.conf.Config()
// 空间对应的机房 一定要按自己属区Zone对象
config.zone = qiniu.zone.Zone_z0
const localFile = filePath
const formUploader = new qiniu.form_up.FormUploader(config)
const putExtra = new qiniu.form_up.PutExtra()
// 文件上传
return new Promise((resolved, reject) => {
formUploader.putFile(uploadToken, key, localFile, putExtra, function (respErr, respBody, respInfo) {
if (respErr) {
reject(respErr)
} else {
resolved(respBody)
}
})
})
}
执行
- 配置执行文件
修改package.json
"scripts": {
"temp":"tsc",
"start":"node dist/app"
},
- 执行
npm run temp //将ts 编译成js文件
npm run start //启动项目