Home > other >  Get processed word file from c# endpoint to nodejs server
Get processed word file from c# endpoint to nodejs server

Time:04-12

I have a nodejs server that sends a GET request with axios to a c# endpoint with json as a parameter. My c# api uses Newtonsoft.Json to deserialize the json, then it reads a word file into memory, and inserts data. The final step I need is for this api to respond by sending the modified document back to the nodejs server. Currently, the c# endpoint is called, and a response is sent back. Upon writing the word document using the archiver library and opening it, a dialogue box appears, saying "Word found unreadable content in export0.docx. Do you want to recover the contents of this document? If you trust the source of this document, click Yes"

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;
    }

Things I've tried

  • Changing the axios responsetype to 'stream', converting the response to a buffer with a function, and writing it to a file
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));

    });
}
  • Changing my c# method to return a 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"); 

Logging the length of byte[] and logging data.length produce 2 different numbers (52107 and 69476, respectively). Is this just a serialization issue? Obviously I'm missing something. Any help would be much appreciated!

CodePudding user response:

Turns out to have been a few things: I used template = WordProcessingDocument.Open(), but never called template.Save() or template.Close() and as such, my changes were never written, and the file was still open. Once I got my byte array output, I used Convert.ToBase64String(output) and returned the string. On the NodeJs side, I changed the responsetype to 'text', and returned Buffer.from(axiosResponse.data, 'base64'); and wrote the file that way.

  • Related