Read application/X-www-form-urlencoded data from Angular 2 in express #796

Open
opened 2017-05-15 17:14:57 +00:00 by xameeramir · 6 comments
xameeramir commented 2017-05-15 17:14:57 +00:00 (Migrated from github.com)

We've got a function which calls an API to upload files + normal form data a.k.a. strings

import { Http, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

... other stuff ...

addDataWithFile(formData) {

  this.formData['logoUrl'] = this.uploader.queue[0];
  var headers = new Headers();
  headers.append('Content-Type', 'application/X-www-form-urlencoded');
  return this.http.post('/AddDataWithFile', formData, {
      headers: headers
    })
    .map((response: Response) => {
      console.log(response.json());
      return response.json();
    })
    .catch((error: Response) {
      console.log(error);
      return Observable.throw(error || 'server error');
    });
}

And the template like:

    <input #myInput type="file" ng2FileSelect (change)="readUrl($event)" [uploader]="uploader" />


  <form #f="ngForm" (submit)="addDataWithFile(f)" >

      <input type="text" maxlength="32" name="nm" [(ngModel)]="Info.Name" #nmField="ngModel" required>

      <label>name*</label>


      <textarea maxlength="500" [(ngModel)]="Info.Desc" name="Desc" #DescField="ngModel"></textarea>
      <label >Description</label>


    <input [disabled]="f.invalid" [class.btn-press]="'clicked' == val" (mousedown)="chk('clicked')" (mouseup)="chk('release')" (click)="addDataWithFile(f)" value="Save">
    <input id="cancel-btn" [disabled]="f.invalid" [class.btn-press]="'clicked1' == val" (mousedown)="chk('clicked1')" (mouseup)="chk('release')" (click)="onClose(f)" type="button" value="Cancel">

  </form>    

The code this.formData['logoUrl'] = this.uploader.queue[0]; gives the reference of the file being uploaded, however on the server side:

// consfiguration for uploading logo file.
const express = require('express');
const uuidV4 = require('uuid/v4');
const multer = require('multer');
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        if (fs.existsSync('./logos/')) {
            cb(null, './logos/')
        }
        else {
            fs.mkdir('./logos/', function () {
                cb(null, './logos/');
            });
        }
    },
    filename: function (req, file, cb) {
        const file_split = file.originalname.split('.')
        const file_ext = file_split[file_split.length - 1];
        cb(null, uuidV4() + '.' + file_ext);
    }
});

const app = express();
const upload = multer({ storage: storage });

let router = express.Router();

... other stuff ...

// add data with file
router.post('/AddDataWithFile', [upload.single('logo'), routes.middleware], (req, res)=>{
    console.log("req.body.logoUrl ", req.body.logoUrl);
});

The value of req.body.logoUrl is coming as undefined.

What is the correct way to upload this file to server?

original reference

We've got a function which calls an API to [upload files][1] + normal form data a.k.a. strings import { Http, Response, Headers } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; ... other stuff ... addDataWithFile(formData) { this.formData['logoUrl'] = this.uploader.queue[0]; var headers = new Headers(); headers.append('Content-Type', 'application/X-www-form-urlencoded'); return this.http.post('/AddDataWithFile', formData, { headers: headers }) .map((response: Response) => { console.log(response.json()); return response.json(); }) .catch((error: Response) { console.log(error); return Observable.throw(error || 'server error'); }); } And the template like: <input #myInput type="file" ng2FileSelect (change)="readUrl($event)" [uploader]="uploader" /> <form #f="ngForm" (submit)="addDataWithFile(f)" > <input type="text" maxlength="32" name="nm" [(ngModel)]="Info.Name" #nmField="ngModel" required> <label>name*</label> <textarea maxlength="500" [(ngModel)]="Info.Desc" name="Desc" #DescField="ngModel"></textarea> <label >Description</label> <input [disabled]="f.invalid" [class.btn-press]="'clicked' == val" (mousedown)="chk('clicked')" (mouseup)="chk('release')" (click)="addDataWithFile(f)" value="Save"> <input id="cancel-btn" [disabled]="f.invalid" [class.btn-press]="'clicked1' == val" (mousedown)="chk('clicked1')" (mouseup)="chk('release')" (click)="onClose(f)" type="button" value="Cancel"> </form> The code `this.formData['logoUrl'] = this.uploader.queue[0];` gives the reference of the file being uploaded, however on the server side: // consfiguration for uploading logo file. const express = require('express'); const uuidV4 = require('uuid/v4'); const multer = require('multer'); const storage = multer.diskStorage({ destination: function (req, file, cb) { if (fs.existsSync('./logos/')) { cb(null, './logos/') } else { fs.mkdir('./logos/', function () { cb(null, './logos/'); }); } }, filename: function (req, file, cb) { const file_split = file.originalname.split('.') const file_ext = file_split[file_split.length - 1]; cb(null, uuidV4() + '.' + file_ext); } }); const app = express(); const upload = multer({ storage: storage }); let router = express.Router(); ... other stuff ... // add data with file router.post('/AddDataWithFile', [upload.single('logo'), routes.middleware], (req, res)=>{ console.log("req.body.logoUrl ", req.body.logoUrl); }); The value of `req.body.logoUrl` is coming as undefined. >What is the correct way to upload this file to server? [1]: https://github.com/valor-software/ng2-file-upload [original reference](http://stackoverflow.com/q/43984944/2404470)
loganfarr commented 2017-06-18 23:31:50 +00:00 (Migrated from github.com)

Multer's documentation says that you can read the file data through req.files, not req.body. Did you try that?

[Multer's documentation](https://github.com/expressjs/multer) says that you can read the file data through `req.files`, not `req.body`. Did you try that?
ravishan110 commented 2017-06-22 14:42:17 +00:00 (Migrated from github.com)

If you are uploading a single file (upload.single), you can access it through req.file, and req.file.location will give you the location of the uploaded file.

If you are uploading multiple files at once (upload.array), you can access it using req.files. req.files is an array, so req.files[i].location should give you the url (Not sure about it though), just check it.

But , in your case, you should try req.file.location.

If you are uploading a single file (`upload.single`), you can access it through `req.file`, and `req.file.location` will give you the location of the uploaded file. If you are uploading multiple files at once (`upload.array`), you can access it using `req.files`. `req.files` is an array, so `req.files[i].location` should give you the url (Not sure about it though), just check it. But , in your case, you should try `req.file.location`.
tarun29061990 commented 2017-08-08 16:43:50 +00:00 (Migrated from github.com)

How it will work if we have Python as a backend. I am only getting the file object, not getting file binary data. SO how I will do that in python?

How it will work if we have Python as a backend. I am only getting the file object, not getting file binary data. SO how I will do that in python?
ravishan110 commented 2017-08-09 04:41:25 +00:00 (Migrated from github.com)

Can you tell more about the object that you are getting in the backend. How are you uploading the file in the server???

Can you tell more about the object that you are getting in the backend. How are you uploading the file in the server???
tarun29061990 commented 2017-08-09 09:37:40 +00:00 (Migrated from github.com)

Frontend Code

this.uploaderOptions.additionalParameter = {"path":"/tmp"};

    this.uploader.onAfterAddingFile = (file)=> {
      file.withCredentials = false;
      this.uploaderOptions.headers = [{name:'Content-Type', value:'image/*'}];
      this.uploader.setOptions(this.uploaderOptions);
    };
    this.uploader.onCompleteItem = (item:any, response:any, status:any, headers:any) => {
         console.log("ImageUpload:uploaded:", item, status, response);
    };

I am getting multipart/form-data at the backend, but when I am uploading it to s3 then the whole image comes black when viewed

Frontend Code ``` this.uploaderOptions.additionalParameter = {"path":"/tmp"}; this.uploader.onAfterAddingFile = (file)=> { file.withCredentials = false; this.uploaderOptions.headers = [{name:'Content-Type', value:'image/*'}]; this.uploader.setOptions(this.uploaderOptions); }; this.uploader.onCompleteItem = (item:any, response:any, status:any, headers:any) => { console.log("ImageUpload:uploaded:", item, status, response); }; ``` I am getting multipart/form-data at the backend, but when I am uploading it to s3 then the whole image comes black when viewed
ravishan110 commented 2017-08-10 08:10:50 +00:00 (Migrated from github.com)

How are you reading multi-part form data at the backend?

How are you reading multi-part form data at the backend?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dc/ng2-file-upload#796