我正在使用“ 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',因为该文件扩展名的文件格式无效。请验证该文件未损坏并且该文件扩展名与该文件的格式匹配。”
亲爱的成员,有什么帮助吗?
答案 0 :(得分:0)
您可以将内容指定为纯字符串,然后以.csv作为文件扩展名将内容转换为Also: hudson.remoting.Channel$CallSiteStackTrace: Remote call to JNLP4-connect connection from nobuild01.sdi.pvt/152.144.34.14:50396
at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1741)
at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:357)
at hudson.remoting.Channel.call(Channel.java:955)
at hudson.FilePath.act(FilePath.java:1036)
at hudson.FilePath.act(FilePath.java:1025)
at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:928)
at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:864)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:113)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:85)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:75)
at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
at hudson.security.ACL.impersonate(ACL.java:290)
at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.NoClassDefFoundError: Could not initialize class jenkins.model.Jenkins
at hudson.scm.SubversionSCM.descriptor(SubversionSCM.java:2584)
at hudson.scm.SubversionSCM.createDefaultSVNOptions(SubversionSCM.java:1085)
at hudson.scm.SubversionSCM.createClientManager(SubversionSCM.java:1075)
at hudson.scm.SubversionSCM$CheckOutTask.invoke(SubversionSCM.java:1002)
at hudson.scm.SubversionSCM$CheckOutTask.invoke(SubversionSCM.java:979)
at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2918)
at hudson.remoting.UserRequest.perform(UserRequest.java:212)
at hudson.remoting.UserRequest.perform(UserRequest.java:54)
at hudson.remoting.Request$2.run(Request.java:369)
at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at hudson.remoting.Engine$1.lambda$newThread$0(Engine.java:93)
at java.lang.Thread.run(Thread.java:745)
Caused: java.io.IOException: Remote call on JNLP4-connect connection from nobuild01.sdi.pvt/152.144.219.14:50396 failed
at hudson.remoting.Channel.call(Channel.java:961)
at hudson.FilePath.act(FilePath.java:1036)
Caused: java.io.IOException: remote file operation failed: c:\Dev at hudson.remoting.Channel@4b1b30ed:JNLP4-connect connection from nobuild01.sdi.pvt/152.144.34.14:50396
at hudson.FilePath.act(FilePath.java:1043)
at hudson.FilePath.act(FilePath.java:1025)
at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:928)
at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:864)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:113)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:85)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:75)
at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
at hudson.security.ACL.impersonate(ACL.java:290)
at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
格式。
要将对象数组转换为csv格式的字符串,可以使用以下代码,然后将返回的字符串作为csv
传递到sendEmailWithAttachments
。
content
以上代码取自to-csv模块。
要在附件设置中指定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));
,请使用text/plain
属性
contentType
如果您遇到任何问题,请告诉我。
答案 1 :(得分:0)
我最终有两种解决方法,都为我工作:
/*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;
}
}
快乐的编码。