title: Upload Excel File with Fetch() Convert To JSON in Memory
body: <p>Looking for best practices on handling Excel File Upload in React/Node and converting to JSON with additional form data.</p>
  
  <p><strong>Requirements:</strong></p>
  
  <ul>
  <li>Post includes form data in addition to Excel File</li>
  <li>Handle Excel File on server with Node.js and Multer in Memory ie., multer.memoryStorage() <strong>(Not Saving File To Server)</strong></li>
  <li><p>Convert Excel data to JSON, then append JSON data with additional form data before sending to MongoDB.   </p></li>
  <li><p>I will also need to process through NGINX on production, which may be an issue uploading the Excel file.  Not an issue in Dev without NGINX.</p></li>
  </ul>
  
  <p><strong>Current working solution on Dev with React/Redux and Node.js:</strong></p>
  
  <ol>
  <li>Fetch() for post to server</li>
  <li>Multer for handling post</li>
  <li><p>xlsx_buffer_json <a href="https://www.npmjs.com/package/xlsx_buffer_json" rel="nofollow noreferrer">https://www.npmjs.com/package/xlsx_buffer_json</a></p>
  
  <p>XLSX Buffer JSON Fix for missing cptable reference:</p></li>
  </ol>
  
  <p>Had to add Externals object to webpack.config:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>       externals: [
           {
            './cptable': 'var cptable'
           },
         ]</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>React Action Code</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>export function importAssets(assetData, importFile) {
      let systemAssetData = new FormData();
      systemAssetData.append('systemId', assetData.systemid);
      systemAssetData.append('productId', assetData.productid);
      systemAssetData.append('fileData', importFile);
  
      const config = {
          method: 'POST',
          headers: {'Accept':'application/json'},
          body: systemAssetData,
      };
  
     return (dispatch) =&gt; {
          dispatch(requestImportAsset(assetData));
  
          return fetch('/asset/importAssets', config)
              .then(response =&gt;
                  response.json().then(assets =&gt; ({assets, response})),
              ).then(({assets, response}) =&gt; {
                  if (!response.ok) {
                      dispatch(requestImportAssetError(assets.message));
                      return Promise.reject(assets.message);
                  }
                  dispatch(requestImportAssetSuccess(assets));
                  return 0;
              }).catch(err =&gt; console.log('Action Error: ', err)); 
      };
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>Node/Express Route Code</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var express = require('express');
  var router = express.Router();
  var requestpromise = require('request-promise');
  var multer  = require('multer');
  var xlsxtojson = require("xlsx_buffer_json")
  var path = require("path");
  var storage = multer.memoryStorage();
  var upload = multer({ storage: storage });
  
  router.post('/importAssets', upload.single('fileData'),  (req, res) =&gt; {
      let config = req.app.get('config');
          try {
              xlsxtojson({
                  input: req.file.buffer,
                  output: null, 
                  lowerCaseHeaders:true
              }, function(err,result){
                  if(err) {
                      console.log('xlsxtojson error:  ' + err);
                      return res.json({error_code:1,err_desc:err, data: null});
                  }
                  result.push({"productid":req.body.productId});
                  result.push({"systemid":req.body.systemId});
                  
                  //send result object JSON to API Server for insert into MongoDB
              });
          } catch (e){
              console.log('corrupt file error:  ' + e);
              res.json({error_code:1,err_desc:"Corupted excel file"});
          }
    res.status(200).send('Excel File Upload Succes')
  });</code></pre>
  </div>
  </div>
  </p>
  
  <p>While this works, it's not the cleanest solution in my mind.   I haven't seen a better working solution to date.</p>
  
  <p>Any thoughts?</p>