Image upload using Node JS


#1

I am trying to upload image from Gallery/Camera.My back-end is Nodejs. I am able to upload a file however it doesn’t appear to be a jpeg.It looks like a some encoded file without any extension and I get this error:

{“code”:3,“source”:“file:///storage/emulated/0/Android/data/io.ionic.starter/cache/1526315072575.jpg”,“target”:“http://192.168.0.100:8000/upload/trade",“http_status”:null,“body”:null,“exception”:"unexpected end of stream on com.android.okhttp.Address@cff2e20a”}

Here is Node Js:

var express = require('express');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var app = express();
var server = require('http').Server(app);
var mongoose = require('mongoose'); 				// mongoose for mongodb
var port = process.env.PORT || 8000; 				// set the port
var database = require('./config/database'); 			// load the database config
var morgan = require('morgan');
var methodOverride = require('method-override');
var io = require('socket.io')(server);
var cors = require('cors');
var multer = require('multer');
var messageId = {};
var fs = require('fs');
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({'extended': 'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({type: 'application/vnd.api+json'})); // parse application/vnd.api+json as json
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(cors());
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  next();
});

 app.use(bodyParser.urlencoded({ extended: false }));
 app.use(bodyParser.json());

var upload = multer({dest :'user-img/'});

var uploadTradeRouter = express.Router();

uploadTradeRouter.post('/trade' , upload.any() , function(req, res, next){
         console.log('trade data called' +req);
});
app.use('/upload' , uploadTradeRouter);
app.listen(port);

This is my uploadimage.ts

import { Component, ViewChild  } from '@angular/core';
import { NavController, Navbar, NavParams ,Platform,AlertController,ToastController, LoadingController, ActionSheetController, ModalController} from 'ionic-angular';
import { NativeStorage } from '@ionic-native/native-storage';
import {FormBuilder, FormGroup, Validators, AbstractControl} from '@angular/forms';
import { Camera} from '@ionic-native/camera';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer';
import { ImagePicker } from '@ionic-native/image-picker';
import { Crop } from '@ionic-native/crop';
import { Http, Response } from '@angular/http';
const URL = "http://192.168.43.50:8000/upload/trade";

 NewImage()
  {
    let imageActionSheet = this.actionSheet.create({
      title:"Select Image Source",
      
      buttons:[
        {
          text:"Use Camera",
          handler:()=>{
           // this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY)
           this.takePicture();
          }
        },
        {
          text:"Choose from Gallery",
          handler:()=>{
            this.browsePicture()
           
          }
        },
        {
          text:'Cancel',
          role:'cancel'
        }
      ]
    });
    imageActionSheet.present();
  }

  public takePicture(){
    var options = {
      quality :70,
      destinationType: this.camera.DestinationType.FILE_URI,
      saveToPhotoAlbum:false,
      correctOrientation:true,      
      sourceType:this.camera.PictureSourceType.CAMERA,
      encodingType: this.camera.EncodingType.JPEG
      
    }; 
    this.camera.getPicture(options).then(data=>{
      this.UploadImage(data)   
    }).catch((err)=>{
      console.log("Camera error :", err)
    }
    )
  }
  UploadImage(imagePath){
    const fileTransfer: FileTransferObject = this.transfer.create();
    let imageURI = imagePath.split('?').shift()
    let loader = this.loadingScreen.create({
      content:"Uploading. Please wait"
    });
    let options = {
      fileKey: "file",
      fileName: 'profilepic',
      chunkedMode: false,
      mimeType: 'image/jpeg',
    
     
    };
   //this.formData = new FormData()
  
    //this.formData.append('photo',{imageURI})
    loader.present();
    //     this.http.post(URL,this.formData).map((res:Response)=>res.json()).subscribe((success)=>{
    //   console.log(success._body);
    // },(error)=>{console.log(error);loader.dismiss()})

    fileTransfer.upload(imageURI,URL,options).then((entry) => {
      
       console.log("Upload Method");
      }, (err) => {
        loader.dismiss();
        console.log("uplaod error>",JSON.stringify(err)
      );
      });
 }

I am not able to understand, where could be the issue ? any pointers would be really helpfull.


#2

I had a 2 part tutorial on image upload with NodeJS a few months ago and for me the mimetype insidet options for the upload looked like this (which worked back then):

   var options: FileUploadOptions = {
      mimeType: 'multipart/form-data'
    };

So perhaps try to send it as multipart/form-data although it sounds counter intuitive. Also, the error is coming from your Android device, right? Looks like the image was not completely transferred to the server, that would explain why the image is not right inside your node app folder after the upload…


#3

That change didn’t help, I have the same thoughts as yours. It is taking lot of time say at least 3 mins, and I am doing it locally. Really don’t understand what is the issue. In the node app folder, I see some encoded file, perhaps its not transferred fully, still breaking my head on it :frowning: