Finally, I have a found a solution to my problem. It may help for other how are facing the same issue.
1) Changed the C# encoding as referenced by @Srikanth
HttpServerUtility.UrlTokenEncode to System.Convert.ToBase64String(bytes);
2) I was saving base64 encode to file in C# and reading it from NodeJS. The problem is saving to file adds addition characters which make problem in decoding it using NodeJS (Always get the corrupted zip) UTF8 problem.
C# Code to for converting zip file to Base64 encoding
using System;
using System.IO;
namespace email_zip
{
public class Program
{
public static void Main(string[] args)
{
byte[] bytes = File.ReadAllBytes("./7738292858_January_February_2017.zip");
string base64 = System.Convert.ToBase64String(bytes);
Console.WriteLine(base64);
}
}
}
NodeJS code for decoding base64 received from C# project and extracting the zip file
Decodes base64 string received from .NET project, Extract the zip
file, and list all files included in decoded zip file
(zipExtractor.js)
'use strict';
/**
* Decodes base64 string received from .NET project, Extract the zip file, and list all files included in decoded zip file
*/
var errSource = require('path').basename(__filename),
fs = require('fs'),
path = require('path'),
async = require('async'),
debug = require('debug')('cs:' + errSource),
AdmZip = require('adm-zip'),
mimeType = require('mime-types'),
ZIP_EXTRACT_DIR = 'zip_extract'; // Default zip extract directory
// Check is zip extract directory exists / not. If not creates the directory
var zipExtractorDir = path.join(__dirname, ZIP_EXTRACT_DIR);
if (!fs.existsSync(zipExtractorDir)) {
fs.mkdirSync(zipExtractorDir);
}
/**
* Callback for getting the decoded Base64 zip file
*
* @callback extractCallback
* @param {Object} err If unable to decode Base64 and save zip file
* @param {Array<Object>} attachments Zip file extracted files
*/
/**
* extract
*
* Decodes base64 string received from .NET project
* Covert to zip file
* Extract the zip file and return all the mine-type and file data information
*
* @param {String} ticketInfo Base64 encoded string
* @param {extractCallback} callback - A callback to decode and zip file extract
*/
function extract(ticketInfo /* Base64 encoded data */ , callback) {
console.time('extract');
async.waterfall([
async.constant(ticketInfo),
base64Decode,
zipExtractor,
deleteFile
], function(err, result) {
console.timeEnd('extract');
debug('extract', 'async.waterfall->err', err);
debug('extract', 'async.waterfall->result', result);
if (err) {
// log.enterErrorLog('8000', errSource, 'extract', 'Failed to extract file', 'Error decode the base64 or zip file corrupted', err);
return callback(err, null);
}
return callback(null, result);
});
}
/**
* Callback for getting the decoded Base64 zip file
*
* @callback base64DecodeCallback
* @param {Object} err If unable to decode Base64 and save zip file
* @param {String} fileName Zip decode file name
*/
/**
* Create file from base64 encoded string
*
* @param {String} ticketInfo Base64 encoded string
* @param {base64DecodeCallback} callback - A callback to Base64 decoding
*/
function base64Decode(ticketInfo, callback) {
var decodeFileName = 'decode_' + new Date().getTime() + '.zip', // Default decode file name
base64DecodedString = new Buffer(ticketInfo, 'base64'); // Decodes Base64 encoded string received from.NET
fs.writeFile(path.join(__dirname, ZIP_EXTRACT_DIR, decodeFileName), base64DecodedString, function(err) {
if (err) {
//log.enterErrorLog('8001', errSource, 'base64Decode', 'Failed to save the base64 decode zip file', '', err);
return callback(err, null);
}
return callback(null, decodeFileName);
});
}
/**
* Callback for getting the decoded Base64 zip extracted file name.
*
* @callback zipExtractorCallback
* @param {Object} err Unable to extract the zip file
* @param {String} fileName Zip decode file name's
*/
/**
* Extract zip file
*
* @param {String} zipFile Decoded saved file
* @param {zipExtractorCallback} callback - A callback to Base64 decoding
*/
function zipExtractor(zipFile, callback) {
try {
var zipFilePath = path.join(__dirname, ZIP_EXTRACT_DIR, zipFile),
zip = new AdmZip(zipFilePath),
zipEntries = zip.getEntries(); // An array of ZipEntry records
zip.extractAllTo( /*target path*/ ZIP_EXTRACT_DIR, /*overwrite*/ true);
var zipFileAttachments = [];
zipEntries.forEach(function(zipEntry) {
if (!zipEntry.isDirectory) { // Determines whether the zipEntry is directory or not
var fileName = zipEntry.name, // Get of the file
filePath = path.join(__dirname, ZIP_EXTRACT_DIR, fileName),
attachment = {
filename: fileName,
path: filePath,
contentType: mimeType.contentType(path.extname(filePath))
};
zipFileAttachments.push(attachment);
}
debug('zipExtractor->', 'attachment', attachment);
});
return callback(null, {
name: zipFile,
attachments: zipFileAttachments
});
} catch (err) {
// log.enterErrorLog('8002', errSource, 'zipExtractor', 'Failed to extract file', 'Error decode the base64 or zip file corrupted', err);
return callback(err, null);
}
}
/**
* Callback for getting the status of deleted decode file
*
* @callback deleteFileCallback
* @param {Object} err Unable to delete the zip file
* @param {Array<Object>} attachment All zip file attachment Object
*/
/**
* Delete decode zip file from the system
*
* @param {String} zipFile Decoded saved file
* @param {deleteFileCallback} callback - A callback to Base64 decoding
*/
function deleteFile(zipFileExtractInfo, callback) {
var fileName = zipFileExtractInfo.name,
filePath = path.join(__dirname, ZIP_EXTRACT_DIR, fileName);
fs.unlink(filePath, function(err) {
if (err && err.code == 'ENOENT') {
//log.enterErrorLog('8003', errSource, 'deleteFile', 'Failed to delete decode zip file', fileName, err);
debug('deleteFile', 'File doest exist, wont remove it.');
} else if (err) {
//log.enterErrorLog('8003', errSource, 'deleteFile', 'Failed to delete decode zip file', fileName, err);
debug('deleteFile', 'Error occurred while trying to remove file');
}
return callback(null, zipFileExtractInfo.attachments);
});
}
module.exports = {
extract: extract
};
Executing C# program from NodeJS and reading Base64 console output.
Decoding using zipExtractor.js.
var zipExtractor = require('./zipExtractor');
console.time('dotnet run');
var exec = require('child_process').exec;
// Follow instruction to set .NET in Mac OS https://www.microsoft.com/net/core#macos
exec('dotnet run', function(error, stdout, stderr) {
console.timeEnd('dotnet run');
if (error) {
console.error(error);
return;
} else if (stderr) {
console.error(stderr);
return;
}
zipExtractor.extract(stdout, function(err, attachments) {
if (err) {
console.error(err);
}
console.info(attachments);
});
});
Output:
dotnet run: 9738.777ms
extract: 155.196ms
[ { filename: '7738292858_January_February_2017.pdf',
path: '/Users/andan/Documents/email_zip/zip_extract/7738292858_January_February_2017.pdf',
contentType: 'application/pdf' } ]