js大文件切片上传断点续传完整代码
在前面两篇文章JavaScript高级 - 纯js实现文件上传大文件切片上传断点续传(客户端)和JavaScript高级 - nodejs+koa2实现文件上传大文件切片上传断点续传(服务器端)中我们分别介绍了文件上传的服务端接口开发和客户端页面功能开发,接下来将为大家附上前后端完整代码
- 服务端完整代码
// server.js
const Koa = require('koa');
const Router = require('koa-router');
const koastatic = require('koa-static');
const fs = require('fs');
const formidable = require('formidable');
const multiparty = require('multiparty');
const SparkMD5 = require('spark-md5');
const path = require('path');
const app = new Koa();
let router = new Router();
//中间件:设置允许跨域
app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*');
//处理OPTIONS请求
ctx.request.methods === 'OPTIONS' ? ctx.body = '请求测试成功' : await next();
});
const host = '127.0.0.1',
port = 3000;
const HOSTNAME = `${
host}:${
port}`;
const SERVER_PATH = `${
__dirname}/upload`;
app.listen(port, function () {
console.log('======================================================================');
console.log(`The server started at port: ${
port}, you can access it by ${
HOSTNAME}`);
console.log('======================================================================');
});
//定义延迟函数
const delay = function delay(interval) {
typeof interval !== 'number' ? interval = 1000 : null;
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve();
}, interval);
});
}
//检测文件是否已经存在
const exists = function exists(path) {
return new Promise((resolve, reject) => {
fs.access(path, fs.constants.F_OK, err => {
if (err) {
resolve(false);
return;
}
resolve(true);
});
});
}
//利用multiparty插件解析前端传来的form-data格式的数据,并上传至服务器
const multipartyUpload = function multipartyUpload(req, autoUpload) {
let config = {
maxFieldsSize: 200 * 1024 * 1024
}
if (autoUpload) config.uploadDir = SERVER_PATH;
return new Promise((resolve, reject) => {
new multiparty.Form(config).parse(req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
resolve({
fields,
files
});
});
});
}
//将传进来的文件数据写入服务器
//form-data格式的数据将以流的形式写入
//BASE64格式数据则直接将内容写入
const writeFile = function writeFile(serverPath, file, isStream) {
console.log(serverPath);
return new Promise((resolve, reject) => {
if (isStream) {
try {
let readStream = fs.createReadStream(file.path);
let writeStream = fs.createWriteStream(serverPath);
readStream.pipe(writeStream);
readStream.on('end', () => {
resolve({
result: true,
message: '上传成功!'
});
});
} catch (err) {
resolve({
result: false,
message: err
})
}
} else {
fs.writeFile(serverPath, file.path, err => {
if (err) {
resolve({
result: false,
message: err
})
return;
}
resolve({
result: true,
message: '上传成功!'
});
});
}
});
}
//上传单个文件(form-data),利用第三方插件multipary解析并上传
router.post('/upload_single_file', async (ctx, next) => {
try {
let {
files
} = await multipartyUpload(ctx.req, true);
let file = (files && files.file.length) ? files.file[0] : {
};
ctx.body = {
code: 0,
message: '文件上传成功',
originalFilename: file.originalFilename,
serverPath: file.path.replace(__dirname, HOSTNAME)
}
} catch (err) {
ctx.body = {
code: 1,
message: '文件上传失败'
}
}
});
//上传单个文件(form-data),利用第三方插件解析但不直接上传,而是将文件重命名后再单独上传
router.post('/upload_single_formdata_rename', async (ctx, next) => {
try {
let {
files,
fields
} = await multipartyUpload(ctx.req, false);
let file = (files && files.file.length) ? files.file[0] : {
};
let filename = (fields && fields.filename.length) ? fields.filename[0] : '';
const filePath = `${
SERVER_PATH}/${
filename}`;
let isExist = await exists(filePath);
if (isExist) {
ctx.body = {
code: 0,
message: '文件已经存在',
originalFilename: filename,
serverPath: file.path.replace(__dirname, HOSTNAME)
}
return;
}
let obj = await writeFile(filePath, file, true);
if (obj.result) {
ctx.body = {
code: 0,
message: '文件上传成功',
originalFilename: filename,
serverPath: filePath.replace(__dirname, HOSTNAME)
}
} else {
ctx.body = {
code: 0,
message: '文件上传失败'
}
}
} catch (ex) {
ctx.body = {
code: 0,
message: ex
}
}
});
//解析post请求参数,content-type为application/x-www-form-urlencoded 或 application/josn
const parsePostParams = function parsePostParams(req) {
return new Promise((resolve, reject) => {
let form = new formidable.IncomingForm();
form.parse(req, (err, fields) => {
if (err) {
reject(err);
return;
}
resolve(fields);
});
});
}
//BASE64上传,该方式只能上传小图片,大图片不建议使用这种方式会造成程序卡死,大图片使用form-data上传
router.post('/upload_base64'