目录
- express+multer上传图片打开乱码
- 原因
- 解决方法
- 简单的node文件上传下载及中文乱码
- 1. 基于MEAN的技术栈
- 2. 在前端代码中放置文件上传按钮和处理表单数据
- 3. 后端接收上传文件
- 4. 处理上传文件的乱码
- 5. 下载文件
- 6. 处理下载文件的乱码
express+multer上传图片打开乱码
原因
由于使用multer处理上传图片时,multer存储的是重命名的文件,文件并没有后缀名导致文件无法在服务器直接打开,手动加上后缀名就能打开文件。
如:
解决方法
引入fs模块将文件重命名存储即可,以下用单文件上传为例:
const fs=require('fs') | |
router.post('/imageUpload',upload.single('avatar'),function (req, res) { | |
console.log(req.file) | |
//获取文件后缀名 | |
var appendName=req.file.originalname.split('.')[1] | |
//fs重命名文件,第一个参数为上传文件绝对路径,第二个参数为相对路径 | |
//第三个参数可选 | |
fs.rename(req.file.path,`tmp/uploads/${req.file.filename}.${appendName}`,function (err) { | |
if (err) throw err | |
}) | |
res.json({msg:'success'}) | |
}) |
简单的node文件上传下载及中文乱码
1. 基于MEAN的技术栈
使用restful风格的接口
2. 在前端代码中放置文件上传按钮和处理表单数据
<div class="upload-file btn btn-sm btn-primary mb-2"> | |
<span><i class="fa fa-upload"></i> Upload</span> | |
<input type="file" class="btn btn-sm btn-primary mb-2" (change)="fileChange($event, topic)" placeholder="Upload file" accept=".csv,.xls"> | |
</div> |
处理上传文件,生成表单数据
fileChange(event, topic) { | |
this.topic = topic; | |
const fileList: FileList = event.target.files; | |
const file: File = fileList[0]; | |
const formData: FormData = new FormData(); | |
formData.append('_id', topic._id); | |
formData.append('file', file, file.name); | |
this.topicService.uploadMark(formData).subscribe((res) => { | |
this.topic.marks = res; | |
this.toast.setMessage('item import successfully.', 'success'); | |
}, error => console.log(error)); | |
} | |
uploadMark(fileData: FormData): Observable<any> { | |
return this.http.post('/api/upload', fileData); | |
} |
3. 后端接收上传文件
文件上传的router
export default function setRoutes(app) { | |
const router = express.Router(); | |
// file uplaod | |
router.route('/upload').post(uploadCtrl.uploadFile); | |
// Apply the routes to our application with the prefix /api | |
app.use('/api', router); | |
} |
在路由中,req的file字段是获取不到上传文件的,或许可以通过设置bodyParser来处理,但我这里使用一个比较常见的库multer。
npm install multer --save | |
import * as path from 'path'; | |
import * as multer from 'multer'; | |
import TopicService from '../services/topic'; | |
export default class UploadCtrl { | |
uploadFile = (req, res) => { | |
const topicService = new TopicService(); | |
// 获取上传文件 | |
const uploading = multer({ | |
dest: path.join(__dirname, '../public/uploads'), | |
}).single('file'); // 这里的file是formData.append('file', file, file.name)里的名称 | |
uploading(req, res, (err) => { | |
if (err) { | |
return console.error(err); | |
} | |
const topicId = req.body._id; | |
const uploadFile = req.file; | |
// 保存数据 | |
const save = async () => { | |
const markList = await topicService.parseMark(uploadFile.path); | |
const db = await topicService.saveDB(topicId, markList); | |
return { | |
markList: markList, | |
db: db, | |
}; | |
}; | |
save().then((result) => { | |
res.status(200).json(result.markList); | |
}, error => { | |
console.error(error); | |
}); | |
}); | |
} | |
} |
4. 处理上传文件的乱码
上传的文件是一个中文的csv,解析时出现了乱码,使用iconv-lite进行转换
npm install iconv-lite --save | |
import * as iconv from 'iconv-lite'; | |
import * as Buffer from 'bufferhelper'; | |
export default class IconvHelper { | |
/** | |
* 用于文件上传的转码 | |
* @param fileStr | |
* @returns {string} | |
*/ | |
static iconv2utf8 = (fileStr) => { | |
return iconv.decode(fileStr, 'gbk'); | |
} | |
/** | |
* 用于文件下载的转码 | |
* @param fileStr | |
* @returns {NodeBuffer} | |
*/ | |
static iconv2gbk = (fileStr) => { | |
return iconv.encode(fileStr, 'gbk'); | |
} | |
} |
bufferhelper是一个buffer的增强类,但这里使用后并不能正确赋值,所以这里暂且没有使用
对csv文件进行解析,生成数组,下一步可以保存到数据库
parseMark = (filePath) => { | |
return new Promise((resolve, reject) => { | |
// 读取文件内容 | |
fs.readFile(filePath, (error, data) => { | |
if (error) { | |
return reject(error); | |
} | |
const text = IconvHelper.iconv2utf8(data); | |
const markList = []; | |
// 将文件按行拆成数组 | |
text.split(/\r?\n/).forEach((line, index) => { | |
const arr = line.split(','); | |
if (index > 0 && arr[0]) { | |
markList.push({ | |
userId: arr[0], | |
username: arr[1], | |
donePageCount: arr[2], | |
areaCount: arr[4], | |
name: arr[6], | |
}); | |
} | |
}); | |
resolve(markList); | |
}); | |
}); | |
} |
5. 下载文件
res.setHeader('Content-disposition', `attachment; filename='${result.name}-member.csv'`); | |
res.setHeader('Content-type', 'text/csv; charset=GBK'); | |
res.end(IconvHelper.iconv2gbk(content)); |
6. 处理下载文件的乱码
由于node.js只支持'ascii', 'utf8', 'base64', 'binary'的编码方式,不支持MS的utf8 + BOM格式,网上有说增加BOM头,如下示:
const msExcelBuffer = Buffer.concat([ | |
new Buffer('\xEF\xBB\xBF', 'binary'), | |
new Buffer(IconvHelper.iconv2gbk(content)) | |
]); |
但实际并没有起作用,最后只是简单的encode成gbk问题得到解决
res.end(IconvHelper.iconv2gbk(content));