我在服務器上使用GridFS存儲Word(.docx)文件。我希望能夠通過使用docx-builder NPM軟件包將文檔合併到一個Word文件中。如何在Meteor中執行服務器端文件處理操作?
這裏是如何,我上傳文件:
Meteor.methods({
uploadFiles: function (files) {
check(files, [Object]);
if (files.length < 1)
throw new Meteor.Error("invalid-files", "No files were uploaded");
var documentPaths = [];
_.each(files, function (file) {
ActivityFiles.insert(file, function (error, fileObj) {
if (error) {
console.log("Could not upload file");
} else {
documentPaths.push("/cfs/files/activities/" + fileObj._id);
}
});
});
return documentPaths;
}
})
我如何去在服務器端做這個?我只能做這個服務器端,因爲我使用的包需要fs
包,不能執行客戶端。
下面是我目前正在嘗試的工作。從客戶端,我打電話給下面的方法(這被聲明爲Meteor.method
):
print: function(programId) {
// Get the program by ID.
var program = Programs.findOne(programId);
// Create a new document.
var docx = new docxbuilder.Document();
// Go through all activities in the program.
program.activityIds.forEach(function(activityId) {
// Create a temporary server side folder to store activity files.
const tempDir = fs.mkdtempSync('/tmp/');
// Get the activity by ID.
var activity = Activities.findOne(activityId);
// Get the document by ID.
var document = ActivityFiles.findOne(activity.documents.pop()._id);
// Declare file path to where file will be read.
const filePath = tempDir + sep + document.name();
// Create stream to write to path.
const fileStream = fs.createWriteStream(filePath);
// Read from document, write to file.
document.createReadStream().pipe(fileStream);
// Insert into final document when finished writinf to file.
fileStream.on('finish',() => {
docx.insertDocxSync(filePath);
// Delete file when operation is completed.
fs.unlinkSync(filePath);
});
});
// Save the merged document.
docx.save('/tmp' + sep + 'output.docx', function (error) {
if (error) {
console.log(error);
}
// Insert into Collection so client can access merged document.
Fiber = Npm.require('fibers');
Fiber(function() {
ProgramFiles.insert('/tmp' + sep + 'output.docx');
}).run();
});
}
然而,當我從ProgramFiles
收集在客戶端下載的最後文件,該文件是一個空的Word文檔。
這裏怎麼回事?
我已將@ FrederickStark的答案納入我的代碼。現在就停留在這部分。
這裏的另一種嘗試:
'click .merge-icon': (e) => {
var programId = Router.current().url.split('/').pop();
var programObj = Programs.findOne(programId);
var insertedDocuments = [];
programObj.activityIds.forEach(function(activityId) {
var activityObj = Activities.findOne(activityId);
var documentObj = ActivityFiles.findOne(activityObj.documents.pop()._id);
JSZipUtils.getBinaryContent(documentObj.url(), callback);
function callback(error, content) {
var zip = new JSZip(content);
var doc = new Docxtemplater().loadZip(zip);
var xml = zip.files[doc.fileTypeConfig.textPath].asText();
xml = xml.substring(xml.indexOf("<w:body>") + 8);
xml = xml.substring(0, xml.indexOf("</w:body>"));
xml = xml.substring(0, xml.indexOf("<w:sectPr"));
insertedDocuments.push(xml);
}
});
JSZipUtils.getBinaryContent('/assets/template.docx', callback);
function callback(error, content) {
var zip = new JSZip(content);
var doc = new Docxtemplater().loadZip(zip);
console.log(doc);
setData(doc);
}
function setData(doc) {
doc.setData({
// Insert blank line between contents.
inserted_docs_formatted: insertedDocuments.join('<w:br/><w:br/>')
// The template file must use a `{@inserted_docs_formatted}` placeholder
// that will be replaced by the above value.
});
doc.render();
useResult(doc);
}
function useResult(doc) {
var out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
saveAs(out, 'output.docx');
}
你嘗試過什麼到目前爲止對話框(可選)?你應該能夠從數據庫查詢文件並將它們傳遞到docx-builder –
@FrederickStark我已經添加了我的工作。 –