express multer上传图片打开乱码

原因

由于使用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));

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

express+multer上传图片打开乱码问题及解决的更多相关文章

  1. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  2. php+croppic.js实现剪切上传图片功能

    最近做项目遇到这样的需求,需要实现裁剪图片上传,接下来通过本文给大家分享基于php+croppic.js实现剪切上传图片功能,需要的朋友可以参考下

  3. Node.js使用Express创建Web项目详细教程

    如果需要入门使用node.js进行web开发,正在学习 nodejs web开发指南 的和想快速了解node.js web开发模式的朋友,相信本文是有一定帮助意义的。

  4. 详解Node.js开发中的express-session

    express-session 是基于express框专门用于处理session的中间件,本篇文章主要介绍了详解Node.js开发中的express-session,有兴趣的可以了解一下

  5. jQuery实现判断上传图片类型和大小的方法示例

    这篇文章主要介绍了jQuery实现判断上传图片类型和大小的方法,结合实例形式分析了jQuery针对上传图片属性获取、判定相关操作技巧,需要的朋友可以参考下

  6. nodejs+express搭建多人聊天室步骤

    本篇文章给大家详细讲解了nodejs+express搭建一个简易的多人聊天室的详细步骤,有兴趣的朋友学习下。

  7. node.js的Express服务器基本使用教程

    express是一个开源的node.js项目框架,下面这篇文章主要给大家介绍了关于node.js的Express服务器基本使用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

  8. 解决VuePress页面乱码问题

    这篇文章主要介绍了解决VuePress页面乱码问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  9. node.js(express)中使用Jcrop进行图片剪切上传功能

    最近在项目开发中遇到了这样的需求就是要实现用户上传头像,并且要保存用户裁切后的部分作为用户头像。下面给大家分享node.js(express)中使用Jcrop进行图片剪切上传功能,需要的的朋友参考下吧

  10. 解决angularjs前后端分离调用接口传递中文时中文乱码的问题

    今天小编就为大家分享一篇解决angularjs前后端分离调用接口传递中文时中文乱码的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

随机推荐

  1. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  2. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  3. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  4. nodejs模块学习之connect解析

    这篇文章主要介绍了nodejs模块学习之connect解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  6. 详解koa2学习中使用 async 、await、promise解决异步的问题

    这篇文章主要介绍了详解koa2学习中使用 async 、await、promise解决异步的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. Node.js编写爬虫的基本思路及抓取百度图片的实例分享

    这篇文章主要介绍了Node.js编写爬虫的基本思路及抓取百度图片的实例分享,其中作者提到了需要特别注意GBK转码的转码问题,需要的朋友可以参考下

  8. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  10. node下使用UglifyJS压缩合并JS文件的方法

    下面小编就为大家分享一篇node下使用UglifyJS压缩合并JS文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

返回
顶部