Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issues in image upload using Express JS and Parse Cloud hosting

I am using Cloud Code and Express, hosted on Parse to upload an image.

Here is the error on Parse log:

 I2015-01-03T13:35:55.199Z] TypeError: Cannot read property 'thumbnail' of undefined
    at app.js:40:25
    at callbacks (express_router.js:161:37)
    at param (express_router.js:135:11)
    at pass (express_router.js:142:5)
    at Router._dispatch (express_router.js:170:5)
    at Object.router (express_router.js:33:10)
    at next (connect_proto.js:240:15)
    at Object.expressInit [as handle] (express_middleware.js:31:5)
    at next (connect_proto.js:240:15)
    at Object.query [as handle] (connect_query.js:44:5)

It seems that Express JS/Parse is not able to understand req.files.XXX. There error is coming in app.js at following line: console.error(req.files.thumbnail.size);

Also, req.files print following error: No Message provided

Here is the recipecontent.ejs code:

<!DOCTYPE html>
<html>
<form method="post" enctype="multipart/form-data" action="/saverecipecontent">
  Enter Recipe Image 1:
  <input type="file" name="thumbnail" id="thumbnail">
  <input type="submit">
</form>

</html>

Here is app.js code:

// These two lines are required to initialize Express in Cloud Code.
var express = require('express');
var app = express();

// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine

app.use(express.bodyParser()); // Middleware for reading request body
app.get('/recipecontent', function(req, res) {

  res.render('recipecontent', {
    recipe_name: 'e.g. Rice Cake'
  });
});

app.post('/saverecipecontent', function(req, res) {

  console.error(req.files.thumbnail.size);
  console.error(req.files.thumbnail.path);
  console.error(req.files.thumbnail.name);
  console.error(req.files.thumbnail.type);


  Parse.Cloud.run('saveRecipeImage', req.body, {
    success: function(result) {
      // result is 'Hello world!'

    },
    error: function(error) {

    }
  });
});
// Attach the Express app to Cloud Code.
app.listen();

Finally here is the main.js code:

  require('cloud/app.js');
  Parse.Cloud.define("saveRecipeImage", function(request, response) {

    var recipeContent = Parse.Object.extend("recipe_content");
    var recipeContentObj = new recipeContent();

    console.error(request.params);

    var file = request.params.thumbnail;

    var name = "photo.jpg";

    var parseFile = new Parse.File(name, file);

    parseFile.save().then(function(parseFile) {
      // The file has been saved to Parse.
      var url = parseFile.url();

      recipeContentObj.set("recipe_imgurl1", url);

      return recipeContentObj.save();

    }, function(error) {
      // The file either could not be read, or could not be saved to Parse.

    });


  });

Please help!

like image 513
Rohit Avatar asked Oct 20 '22 19:10

Rohit


2 Answers

I raised this bug in Parse, here is the update:

The middleware we support for express.js does not support file uploads.

What you can do instead is sending the file contents as base64 to your endpoint and create the Parse.File object from this data.

Here is the updated code utilizing file contents as base64 to endpoint and creating Parse.File object:

Here is the layout.ejs code

< html >
  < head >
  < script src = "//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" > < /script>
     <script src="/ / cdnjs.cloudflare.com / ajax / libs / underscore.js / 1.4.4 / underscore - min.js "></script>
    <!--  <% if (locals.title) { %> -->
       <!-- <title><%= title %></title>
     <% } else { %>
       <title>AnyImg</title>
     <% } %> -->
     <link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
     <script src=" / javascripts / backbone.js "></script>
     <script src="
https: //www.parsecdn.com/js/parse-1.2.8.min.js"></script>
  < script >
  Parse.initialize("n47hKoBkN2vbAAjIPd8rj6Dnc9P6zKYIlXvlZo3x", "a960Z8aOzTNOaKMUcvDQ7lvzT2v2VTHABh6lAdNx"); < /script>
     <script type="text/javascript
" src=" / javascripts / main.js "></script>
  </head>

  <body>
    <div id="
content ">
      <div id="
bar ">
        <h1>File Upload</h1>
      </div>
      
      <div id="
main ">
            <form id="
upload ">
              <div class="
outer ">
                <div>
                  <input type="
text " name="
title " placeholder="
Untitled " />
                  <input id="
asd " type="
file " />
                </div>
              </div>
          </form>
          <img id="
img " src="
" />
          <div id="
base "></div>

      </div>
    </div>
  </body>
</html>

// These two lines are required to initialize Express in Cloud Code.
var express = require('express');
var app = express();

// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine


app.use(express.json());
app.use(express.urlencoded());

app.get('/', function(req, res) {

  res.render('layout', {
    recipe_name: 'e.g. Rice Cake'
  });
});

app.post('/newUploadImage', function(req, res) {


  var file = new Parse.File("logo.png", {
    base64: req.body.image
  });

  file.save().then(function() {
    console.log("file saved");

    console.log(file.url());

  });
  if (req.params.image) {
    console.log("data found12345");
  }

});
app.listen();

Here is the image js

var base64Data;
var imageName = '';

function readImage(input) {
  if (input.files && input.files[0]) {
    imageName = input.files[0].name;
    var FR = new FileReader();
    FR.onload = function(e) {
      $('#img').attr("src", e.target.result);
      $('#base').text(e.target.result);
      base64Data = e.target.result;
      var datObj = {
        image: e.target.result,
        name: imageName
      };
      var test = {
        image: '12sds'
      };
      $.ajax({
        type: "POST",
        data: datObj,
        url: '/newUploadImage',
        dataType: "json",
        success: function(msg) {
          alert(msg.url);
          console.log();

        },
        error: function(errormsg) {
          console.log(errormsg);
          alert("Sorry, there was an error uploading the image.");
        }
      });

    };
    FR.readAsDataURL(input.files[0]);
  }
}



$(function() {
  // Make all of special links magically post the form
  // when it has a particular data-action associated

  $("#asd").change(function() {

    readImage(this);
    alert('Test');

  });


});

Thanks!

like image 108
Rohit Avatar answered Oct 27 '22 18:10

Rohit


It looks like you're trying to use body-parser middleware to parse a multipar body but as stated on the github page of body-parser itself:

This does not handle multipart bodies, due to their complex and typically large nature.

You need another parser to handle multipart bodies. I suggest you multer but there are many others available.

like image 21
Edo Avatar answered Oct 27 '22 17:10

Edo