将处理后的word文件从c#端点获取到nodejs服务器



我有一个nodejs服务器,它用axios向一个以json为参数的c#端点发送GET请求。我的c#api使用Newtonsoft.Json对Json进行反序列化,然后将一个word文件读取到内存中,并插入数据。我需要的最后一步是让这个api通过将修改后的文档发送回nodejs服务器来做出响应。目前,调用了c端点,并发回一个响应。在使用archiver库编写单词文档并打开它时,出现一个对话框,上面写着";Word在export0.docx中发现无法读取的内容。是否恢复此文档的内容?如果您信任此文档的来源,请单击"是";

async exportToDotnet() {
return await axios.get(`https://localhost:8082/test/${JSON.stringify(this)}`, { responseType: 'arrayBuffer' }).catch(err => {
console.log(`ERR `, err);
}).then((axiosResponse) => {
const data = axiosResponse.data;
console.log(`DATA `, data);
console.log(`DATA LENGTH '${data.length}'`);
return data;
});
}
async function writeZipFile(resultFromExportToDotnet) {
const output = createWriteStream('exported.zip');
output.on("close", () => {
console.log("success????");
});
const archive = archiver('zip');
archive.on('error', (err) => {
console.log('error in archive ', err);
});
archive.append(form, { name: `export0.docx` });
archive.pipe(output);
await archive.finalize();
}
[HttpGet("test/{json}")]
public byte[] ExportDocumentBuffer(string json)
{
Console.WriteLine("Called");
//Converts the json passed in to a FormInstance Object
FormInstance form = JsonConvert.DeserializeObject<FormInstance>(json);
//Read the dotx into memory so we can use it. Would it be better to just use System.IO.File.ReadAllBytes()?
MemoryStream dotxBytes = ReadAllBytesToMemoryStream("test.dotx");
//Read the file bytes into a WordProcessingDocument that we can edit
WordprocessingDocument template = WordprocessingDocument.Open(dotxBytes, true);
template.ChangeDocumentType(WordprocessingDocumentType.Document);
template = ParseFormAndInsertValues(form, template);
byte[] output = dotxBytes.ToArray();
Console.WriteLine($"BYTES '{output.Length}'");
return output;
}
///<summary>Reads all Bytes of the provided file into memory</summary>
///<param name="path">The path to the file</param>
///<returns>A MemoryStream of the file data</returns>
public static MemoryStream ReadAllBytesToMemoryStream(string path)
{
byte[] buffer = System.IO.File.ReadAllBytes(path);
MemoryStream destStream = new MemoryStream(buffer.Length);
destStream.Write(buffer, 0, buffer.Length);
destStream.Seek(0, SeekOrigin.Begin);
return destStream;
}

我尝试过的东西

  • 将axios响应类型更改为"stream",使用函数将响应转换为缓冲区,并将其写入文件
function stream2buffer(stream) {
return new Promise((resolve, reject) => {
const _buf = [];
stream.on("data", (chunk) => _buf.push(chunk));
stream.on("end", () => resolve(Buffer.concat(_buf)));
stream.on("error", (err) => reject(err));
});
}
  • 更改我的c#方法以返回HttpResponseMessage
HttpResponseMessage result = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new ByteArrayContent(dotxBytes.ToArray())
};
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "exampleName.docx"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 

记录字节[]的长度和记录data.length会产生两个不同的数字(分别为52107和69476(。这只是一个序列化问题吗?显然我错过了什么。任何帮助都将不胜感激!

原来有几件事:我使用了template = WordProcessingDocument.Open(),但从未调用过template.Save()template.Close(),因此,我的更改从未写入,文件仍然打开。得到字节数组输出后,我使用Convert.ToBase64String(output)并返回字符串。在NodeJ方面,我将responsetype更改为"text",并返回Buffer.from(axiosResponse.data, 'base64');并以这种方式编写文件。

最新更新