【问题标题】:how to send an Excel file to an email using nodemailer module如何使用 nodemailer 模块将 Excel 文件发送到电子邮件
【发布时间】:2019-03-31 13:38:06
【问题描述】:

我正在使用“nodemailer”模块将 Excel 文件作为电子邮件的附件发送。

注意:我在附件中传递给“内容”的是一个对象数组。

 function sendEmailWithAttachments(recipientEmailId, subject, content, next) {

        var ormMailerInfo = getORMMailerInfo();
        var transporter = nodemailer.createTransport(smtpTransport({
            host: ormMailerInfo.orm_mailer_host,
            secure: ormMailerInfo.orm_mailer_secure,
            port: ormMailerInfo.orm_mailer_port,
            auth: {
                user: ormMailerInfo.orm_mailer_user,
                pass: ormMailerInfo.orm_mailer_pass
            }
        }));

        transporter.sendMail({
            from: ormMailerInfo.orm_mailer_user,
            to: recipientEmailId,
            subject: subject,
            attachments: [
                {   /* the uniqueness of my question begins from here */
                    // file being sent is Excel file as '.xlsx' indicates
                    filename: subject + '.xlsx',
                    // content/data being sent an array of objects
                    content: new Buffer(content,'utf-8')
                }
                ]
        }, next);
    }

我已经成功发送和接收它,但是打开excel文件时,它显示以下错误:

“Excel 无法打开文件 'filename.xlsx',因为文件扩展名的文件格式无效。验证文件没有损坏并且文件扩展名与文件格式匹配。”

有什么帮助吗,亲爱的会员?

【问题讨论】:

  • 您使用的是哪个操作系统?试试.csv 扩展
  • 如何生成 XLSX 内容?创建 CSV 文件并不是那么简单。也许您需要使用一些库,例如npmjs.com/package/xlsx
  • @Suresh Prajapati,我的操作系统是 Windows 10。我尝试使用 .csv 扩展名并且 excel 文件打开良好,但文件中的数据只是 [object Object] [object Object]
  • @Suresh Prajapati,对不起,这个 [object Object] [object Object] 是由于我所做的这个改变: content: content.toString() 但是当我使用这个时: content: new Buffer(content ,'utf-8'),该文件也可以很好地打开,但根本没有数据,这意味着它只是一个空文件!

标签: node.js nodemailer


【解决方案1】:

我最终有两种方法可以解决这个问题,并且都对我有用:

      /*1. using `to-csv` module -> `npm i to-csv`*/
      var toCsv = require('to-csv');
      attachments: [{filename: subject + '.csv',content: toCsv(content)}]

     or

     /* 2. using `json2csv` module -> npm i json2csv*/
     attachments: [{filename: subject + '.csv',content:json2csv(content)}]

       function json2csv(content){
       const { Parser } = require('json2csv');
       var fields = getFields(content);
       return new Parser({ fields }).parse(content);

       function getFields(content){
            var fields = [];
            for(var i = 0; i < content.length; i++){
                fields = Object.keys(content[i]);
                if(fields.length > 0)
                    break;
            };
            return fields;
        }
        }

编码愉快。

【讨论】:

    【解决方案2】:

    您可以将内容指定为纯字符串并将内容转换为csv 格式,并以.csv 作为文件扩展名。

    要将对象数组转换为 csv 格式的字符串,您可以使用以下代码,然后将返回的字符串作为 content 传递给您的 sendEmailWithAttachments

    var isArray = Array.isArray
      , keys = Object.keys;
    
    CSV.CHAR_RETURN = 0xd;
    CSV.CHAR_NEWLINE = 0xa;
    CSV.DELIMITER = 0x2c;
    CSV.CHAR_ENCAPSULATE = 0x22;
    
    function head (a) {
      return a[0];
    }
    
    function tail (a) {
      return a[a.length -1];
    }
    
    function char (c) {
      return 'number' === typeof c
        ? String.fromCharCode.apply(null, arguments)
        : c;
    }
    
    function needsEncapsulation (string) {
      return !!string && (
              string.toString().indexOf(char(CSV.DELIMITER)) >= 0 ||
              string.toString().indexOf(char(CSV.CHAR_RETURN)) >= 0 ||
              string.toString().indexOf(char(CSV.CHAR_NEWLINE)) >= 0 ||
              string.toString().indexOf(char(CSV.CHAR_ENCAPSULATE)) >= 0
            );
    }
    
    function encapsulate (string) {
      var wrapperChar = char(CSV.CHAR_ENCAPSULATE)
        , replaceWith = "\\" + char(CSV.CHAR_ENCAPSULATE)
        , escapedValue = string.toString().replace(new RegExp(wrapperChar, 'g'), replaceWith);
    
      return wrapperChar + escapedValue + wrapperChar;
    }
    
    /**
     * Parses an array of objects to a CSV output
     */
    
    // try { module.exports = CSV; } catch(e) {}
    function CSV (objects, opts) {
      if ('object' !== typeof objects) throw new TypeError("expecting an array");
    
      opts = 'object' === typeof opts
        ? opts
        : {};
    
        objects = isArray(objects)
          ? objects.slice()
          : [objects];
    
          if (!objects.length) throw new Error("expecting at least one object");
    
          var headers = keys(head(objects))
            , buf = [];
    
          while (objects.length) {
            var lbuf = []
              , object = objects.shift();
    
            for (var i = 0 ;i < headers.length; ++i) {
              var header = headers[i];
    
              if (lbuf.length) lbuf.push(char(CSV.DELIMITER));
              object[header] = needsEncapsulation(object[header])
                ? encapsulate(object[header])
                : object[header];
    
                lbuf.push(object[header]);
            }
    
            buf.push(lbuf.join(''));
            buf.push(char(CSV.CHAR_RETURN, CSV.CHAR_NEWLINE));
          }
    
          return false !== opts.headers
            ? [].concat(headers.join(char(CSV.DELIMITER)), char(CSV.CHAR_NEWLINE)).concat(buf).filter(Boolean).join('')
            : buf.filter(Boolean).join('');
    }
    
    
    var data = [];
     
    for (var i = 0; i < 10; ++i) {
        data.push({ 
            id: Math.random().toString(16).slice(2), 
            value: data.length % 2 
        });
    }
     
    console.log(CSV(data));

    以上代码取自to-csv模块。

    要在附件设置中指定text/plain,请使用contentType 属性

    attachments: [
      {   
        filename: 'youfile_name.csv',
        content: yourContent,
        contentType: 'text/plain'
      }
    ]
    

    如果您遇到任何问题,请告诉我。

    【讨论】:

    • @CCC 你先试试npm i to-csv 吗?
    • @CCC 您的代码似乎有些问题。您可以添加您的代码并更新问题吗?
    • 好的。但是执行 npm i to-csv 消除了发布函数的需要,因为这两行按预期完成了工作: var toCsv = require('to-csv'); toCsv(内容);
    • @CCC 是的,要么使用那个包,要么在你的项目中使用那个代码,两者都可以解决问题。
    猜你喜欢
    • 2018-07-11
    • 1970-01-01
    • 2015-05-19
    • 2021-12-28
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多