当前端的ueditor.config.js访问的地址是ueditor/ue等时候.后端路由接收。进ue方法
import ueditor from "../service/ueditor/index";
import BaseController from "../../core/BaseController";
class Ueditor extends BaseController{
async ue(){
this.body = await ueditor('public',this.ctx);
}
}
module.exports = Ueditor;
2.ueditor界面配置上传等内容
import * as fs from 'fs';
import * as http from 'http';
import * as https from 'https';
import * as path from 'path';
import upload,{base64Image,fileFormat,getSuffix } from './../upload';
import * as multer from 'koa-multer';
//获取ueditor配置文件
import config from './../config';
//获取全局配置文件
import nconfig from '../../../config';
//同步遍历文件
export const eachFileSync = (dir,findOneFile)=>{
const stats = fs.statSync(dir);
if(stats.isDirectory()){
fs.readdirSync(dir).forEach(file=>{
eachFileSync(path.join(dir,file),findOneFile);
})
}else{
findOneFile(dir,stats);
}
}
//处理上传保存路径
export const setFullPath = (dest) =>{
const date = new Date();
const map = {
t: date.getTime(), // 时间戳
y: date.getFullYear(), // 年
m: date.getMonth() + 1, // 月
d: date.getDate(), // 日
h: date.getHours(), // 时
i: date.getMinutes(), // 分
s: date.getSeconds(), // 秒
}
return dest.replace(/\{([ymdhis])\1*\}|\{time\}|\{rand:(\d+)\}/g, function(all:any, $1:any, $2:any) {
if ($1 !== void 0) {
const v = String(map[$1]);
const l = all.length;
if ($1 != 'y') {
return l > 3 && Number(v) <= 9 ? '0' + v : v;
}
return v.substr(6 - l);
}
if (all === '{time}') return String(map.t);
return String(Math.random()).substr(2, Number($2) || 6);
});
}
//抓取网络图片
const catchImage = (url:string) =>{
const request = /^https:\/\//.test(url) ? https.request : http.request;
let image = url.match(/^(:?https?\:)?\/\/[^#?]+/)[0]
let originalname = image.substr(image.lastIndexOf('\/') + 1)
let contentType = ''
let base64Data = ''
return new Promise((resolve, reject) => {
const req = request(url, (res) => {
contentType = res.headers['content-type']
res.setEncoding('base64')
res.on('data', (chunk) => {
base64Data += chunk
})
res.on('end', () => resolve({contentType, base64Data, originalname}))
})
req.on('error', (err) => resolve({error: true}))
req.end()
})
}
//ueditor上传方法
const ueditor = async (dir:any,ctx,next) =>{
let ueOpts : any = [];
if(typeof dir === 'object'){
ueOpts = Array.isArray(dir) ? dir : ueOpts.push('public');
}else{
ueOpts.push(dir || 'public')
}
const publicDir = path.resolve(ueOpts[0]);
const conf = Object.assign({},config,ueOpts[1] || {});
const uploadType = {
[conf.imageActionName]: 'image',
[conf.scrawlActionName]: 'scrawl',
[conf.catcherActionName]: 'catcher',
[conf.videoActionName]: 'video',
[conf.fileActionName]: 'file',
}
const listType = {
[conf.imageManagerActionName]: 'image',
[conf.fileManagerActionName]: 'file',
};
let result = {};
let {action,start = 0,callback} = ctx.query;
start = parseInt(start);
//上传文件
if(Object.keys(uploadType).includes(action)){
const actionName = uploadType[action];
let pathFormat = setFullPath(conf[actionName + 'PathFormat']).split("/");
let filename = pathFormat.pop();
try{
switch(action){
//涂鸦类型图片
case conf.scrawlActionName :
let base64Data = ctx.request.body[conf[actionName + 'FieldName']];
let base64Length = base64Data.length;
if(base64Length - (base64Length /8) * 2 > conf[actionName + 'MaxSize']){
throw new Error('picture too big')
}
ctx.req.file = base64Image(base64Data,publicDir,{
destination : path.join(publicDir,...pathFormat)
})
result = Object.assign({state: 'SUCCESS',code:0}, fileFormat(ctx.req.file))
break;
//抓取远程图片
case conf.catcherActionName:
const sources = ctx.request.body[conf[actionName + 'FieldName']]
let list = []
let images = []
sources.forEach((url) => {
images.push(catchImage(url).then((image:any) => {
if(image.error){
list.push({state: 'ERROR',code:0, source: url})
}else{
let base64Data = image.base64Data;
let base64Length = base64Data.length;
if(base64Length - (base64Length / 8) * 2 > conf[actionName + 'MaxSize']){
list.push({state: 'Picture too big',code:0, source: url})
}else{
// 重新获取filename
filename = setFullPath(conf[actionName + 'PathFormat']).split('/').pop()
if(filename === '{filename}'){
filename = image.originalname.replace(/\.\w+$/, '')
}
if(/^image\/(\w+)$/.test(image.contentType)){
base64Data = 'data:'+ image.contentType +';base64,' + base64Data
}
console.log(base64Data);
list.push(Object.assign({state: 'SUCCESS', source: url}, fileFormat(
base64Image(base64Data, publicDir, {
destination: path.join(publicDir, ...pathFormat),
filename
})
), {original: image.originalname}))
}
}
return image
}))
})
await Promise.all(images)
result = {state: 'SUCCESS',code:0, list}
break;
default :
await upload(publicDir, {
storage : multer.diskStorage({
destination: path.join(publicDir, ...pathFormat),
filename (req, file, cb) {
//保存原名称
if(filename === '{filename}'){
filename = file.originalname
}else{
filename += getSuffix(file.originalname)
}
// const fileFormat = (file["originalname"].split("."));
// const fileFormat = file.originalname.substr(filename.lastIndexOf('.')).toLowerCase()
// cb(null,Date.now() + "." + fileFormat);
cb(null, filename)
}
})
,
limits: {
fileSize: conf[actionName + 'MaxSize']
},
allowfiles: conf[actionName + 'AllowFiles']}).single(conf[actionName + 'FieldName'])(ctx, next)
result = Object.assign({state: 'SUCCESS'}, fileFormat(ctx.req.file));
break;
}
}catch(err){
console.log(err);
result = {state: err.message}
}
}else if(Object.keys(listType).includes(action)){
const actionName = listType[action]
let files = []
eachFileSync(path.join(publicDir, conf[actionName + 'ManagerListPath']), (file, stat) => {
if(conf[actionName + 'ManagerAllowFiles'].includes(getSuffix(file))){
const url = nconfig.nowUrl + file.replace(publicDir, '').replace(/\\/g, '\/')
const mtime = stat.mtimeMs
files.push({url, mtime})
}
})
result = {
list: files.slice(start, start + conf[actionName + 'ManagerListSize']),
start: start,
total: files.length,
code : 0,
state: 'SUCCESS'
}
}else if(action === 'config'){
result = conf;
}else{
result = {state:'FAIL',code:400}
}
return await callback ? [callback] + '(' + JSON.stringify(result) + ')' : JSON.stringify(result);
}
export default ueditor;
3.upload设置上传文件路径等
/**
* 单文件上传:upload().single(fieldname)
* 多文件上传:upload().array(fieldname[, maxCount])
* 多表单上传:upload().fields([{name: 'avatar', maxCount: 1}, {name: 'gallery', maxCount: 1}])
*/
import * as fs from 'fs';
import * as path from 'path';
import * as multer from 'koa-multer';
//默认静态目录
let publicDir = '';
//同步创建文件目录
export const mkdirsSync = (dirname:string) =>{
if(fs.existsSync(dirname)){
return true;
}else{
if(mkdirsSync(path.dirname(dirname))){
fs.mkdirSync(dirname);
return true;
}
}
}
//获取文件后缀
export const getSuffix = (filename:string) => {
return filename.substr(filename.lastIndexOf('.')).toLowerCase();
}
//存储方式
export const diskStorage = multer.diskStorage({
destination(req,file,cb){
let dir = "";
let type = "file";
file.mimetype.replace(/image|video/g, (v) => {
return type = v
})
dir = path.join(publicDir, 'upload', type)
mkdirsSync(dir)
cb(null, dir)
},
filename(req,file,cb){
cb(null, Date.now() + (Math.random().toString().substr(2,6)) + getSuffix(file.originalname))
}
})
//处理上传后返回的数据格式
export const fileFormat = (data) =>{
console.log(data);
let { originalname :original , filename: title, path: url, size } = data;
const type = getSuffix(title)
url = url.replace(publicDir, '').replace(/\\/g, '\/')
return { original, title, type, url, size }
}
//保存base64类型图片
export const base64Image = (base64Data,dir,options) =>{
if(typeof dir === 'object'){
options = dir
dir = ''
}
publicDir = path.resolve(dir || 'public')
let dest = ''
let ext = '.png'
let { destination, filename } = Object.assign({
destination: path.join(publicDir, 'upload', 'image'),
filename: Date.now() + (Math.random().toString().substr(2,6))
}, options || {})
base64Data = base64Data.replace(/^data:image\/(\w+);base64,/, (all, e) => {
ext = e === 'jpeg' ? '.jpg' : '.' + e
return ''
})
filename += ext
dest = path.join(destination, filename)
mkdirsSync(destination)
fs.writeFileSync(dest, base64Data, 'base64')
const stat = fs.statSync(dest)
return { originalname: '', filename, path: dest, size: stat.size }
}
//上传文件
const upload = (dir,options) =>{
if(typeof dir === 'object'){
options = dir;
dir = "";
}
publicDir = path.resolve(dir || 'public')
const allowfiles = options.allowfiles || '*' // 文件类型,['.jpg', '.png']
const fileFilter = (req, file, cb) => {
if(allowfiles === '*' || allowfiles.includes(getSuffix(file.originalname))){
cb(null, true)
}else{
cb(new Error('Unsupported file type'), false)
}
}
return multer(Object.assign({
storage: diskStorage,
fileFilter,
limits: {
files: 20, // 单次上传文件最大数量
fileSize: 2 * 1024 * 1024, // 文件最大长度 (字节单位)
},
}, options))
}
export default upload;