Hi All,
I’m trying to upload a file from the browser with ng2-file-upload and without Cordova.
The node/express server works fine when I test in Postman. However, it’s not working in Ionic. Oddly, it doesn’t say it fails in Chrome’s Network tab.
The app.js file is:
// npm i -g multer
// npm i -g nodemon
var express = require('express'),
multer = require('multer'),
fs = require('fs'),
app = express(),
http = require("http"),
multer = require('multer'),
server = http.createServer(app),
router = express.Router(),
path = require('path');
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
res.header('Access-Control-Allow-Origin', 'http://localhost:8100');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
//res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
next();
});
var middleware = [
express.static(path.join(__dirname, './uploads/'))
]
app.use(middleware);
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/')
},
filename: function (req, file, callback) {
var datetimestamp = Date.now();
console.log("Filename " + file.originalname);
callback(null, file.originalname);
},
onFileUploadStart: function (file) {
console.log(file.originalname + ' is starting ...');
},
onFileUploadComplete: function (file) {
console.log(file.fieldname + ' uploaded to ' + file.path);
}
});
var upload = multer().any('selectedFile')
//**THIS IS MANDATORY, WITHOUT THIS NOT WORK**
app.use(multer({
storage:storage
}).any('selectedFile'));
app.get('/', (req, res) => res.end('Hello root!!'))
app.get('/api', function (req, res) {
res.end('You're using a GET, not a POST');
});
//app.use('/api', router);
app.post('/api', function (req, res, next) {
upload(req,res,function(err){
if(err){
res.status(500).json({'success':false});
return;
}
res.status(200).json({success:true,message:"File was uploaded successfully !"});
});
});
var PORT = process.env.PORT || 3001;
app.listen(PORT, function () {
console.log('Working on port ' + PORT);
});
To test in Postman,
New > Get > (change “GET” dropdown to “POST” > path is “http://localhost:3001/api”,
The set the Params > Body > Key = “selectedFile”.
Next to Key, set the “Text” dropdown to “File” and select any test file.
Press Send.
Here’s the Ionic code:
home.ts
import { Component } from '@angular/core';
import { FileUploader } from 'ng2-file-upload';
const URL = 'http://localhost:3001/api/';
@Component({
selector: 'home-page',
templateUrl: './home.html'
})
export class HomePage {
uploader:FileUploader;
hasBaseDropZoneOver:boolean;
hasAnotherDropZoneOver:boolean;
response:string;
constructor() {
this.uploader = new FileUploader({
url: URL,
disableMultipart: true, // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
formatDataFunctionIsAsync: true,
formatDataFunction: async (item) => {
return new Promise( (resolve, reject) => {
resolve({
name: 'selectedFile',
filename: item._file.name,
contentType: item._file.type,
/*
name: item._file.name,
length: item._file.size,
contentType: item._file.type,
date : item._file.lastModifiedDate
*/
});
});
}
});
this.hasBaseDropZoneOver = false;
this.hasAnotherDropZoneOver = false;
this.response = '';
this.uploader.response.subscribe( res => this.response = res );
}
public fileOverBase(e:any):void {
this.hasBaseDropZoneOver = e;
}
public fileOverAnother(e:any):void {
this.hasAnotherDropZoneOver = e;
}
public showFunction(): void {
var x = document.getElementById("hiddenDiv");
if (x.style.display === "none")
x.style.display = "block";
else
x.style.display = "none";
}
public DisplaySize(item:any): string {
let b: number = 0;
if (item && item.file)
b = item.file.size;
if (b < 1024)
return b + " bytes";
b /= 1024; // convert to KB
if (b < 1024)
return b.toFixed(2) + " KB";
b /= 1024; // convert to MB
return b.toFixed(2) + " MB";
}
}
home.html
<ion-content style="background-color: #842024" >
<div class="container">
<div class="row">
<div class="col-md-3">
<div ng2FileDrop
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="well my-drop-zone">
<h5 class="drag-label"> Drag File(s) Here To Upload </h5>
</div>
<br/>
<form action='#' onsubmit="return false;">
<input type="file" id="filename" name="selectedFile" ng2FileSelect [uploader]="uploader" multiple/><br/>
</form>
</div>
</div>
</div>
<hr />
<div class="container" id="containerdiv">
<div class="col-md-9" id="resultsdiv">
<div class="results">
<p style="font-size:15px; text-align:center; color: #842024; text-transform: uppercase"> Staging Area </p>
<p> File Queue: {{ uploader?.queue?.length }} </p><br/>
<div class="progressdiv">
<button type="button" class="btn btn-success btn-s" (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
<span class="glyphicon glyphicon-upload"></span>
Upload all
</button>
<button type="button" class="btn btn-warning btn-s" (click)="uploader.cancelAll()" [disabled]="!uploader.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span>
Cancel all
</button>
<button type="button" class="btn btn-danger btn-s" (click)="uploader.clearQueue()" [disabled]="!uploader.queue.length">
<span class="glyphicon glyphicon-trash"></span>
Remove all
</button>
<br/><br/><br/>
<div id="hiddenDiv">
<div class="resultsSummary" id="SpanContainer">
<span class="block" style="float:left!important;text-transform:uppercase"><br/>Upload Log</span> <br/><br/><br/>
<div *ngFor="let item of uploader.queue" >
<div class="row" *ngIf="item.isSuccess">
<br/>
<span class="block">
<hr style= "border-bottom: 1px solid gray; width:20%"/>
{{ response }} - {{ item?.file?.name }} {{ item?.file?.lastModifiedDate }}
</span>
<br/><br/>
</div>
</div>
</div>
</div>
</div>
<table class="table">
<thead>
<tr>
<th width="10%">File Name</th>
<th width="10%">Size</th>
<th width="10%">Progress</th>
<th width="10%">Status</th>
<th width="10%">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of uploader.queue">
<td><strong>{{ item?.file?.name }}</strong></td>
<td>
{{ DisplaySize(item) }}
</td>
<td>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar progress-bar-striped bg-danger" role="progressbar" style="width: 75%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" [ngStyle]="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td class="text-center">
<span *ngIf="item.isSuccess"><i class="glyphicon glyphicon-ok" style="color:red"></i></span>
<span *ngIf="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span *ngIf="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td no-wrap>
<button type="button" class="btn btn-danger btn-s" (click)="item.remove()">
<span class="glyphicon glyphicon-trash"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</ion-content>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
home.scss
page-home {
#containerdiv { margin-top: 50px }
#resultsdiv { border: dotted 3px gray; width: 70%; background-color: white; border-radius: 5px }
#containerdiv h3 { color: white; text-transform: uppercase; font-size:17px; bottom:480px; position: absolute; float:right; right: 380px }
.my-drop-zone { border: dotted 3px #842024; height: 250px; background-color: white; border-radius: 5px; width:800px; margin-top:10px; margin-left: -40px }
.container { width: 80% }
.nv-file-over { border: solid 3px black; }
.drag-label { color: #cccccc; margin-top: 110px; text-align: center }
.title-label { margin-left:100px; color: black; text-transform:uppercase }
.navbar { width:100% !important }
.results { margin-top: 30px; margin-left: 30px; color: darkgray }
.results p { color: #191919; float: center; text-transform: none; font-weight: 200; line-height: 1em; font-size:12px; font-weight:bold; margin-left:-30px; margin-top: -10px }
.results th { color: black; text-transform: none; font-weight: 100; line-height: 1em; font-style: italic; opacity: 0.8; font-size:17px }
.progressdiv { position:absolute; bottom: 100px; right:-350px }
.dropbtn { background-color: darkred; color: white; padding: 16px; font-size: 12px; border: none }
.dropdown { position: relative; display: inline-block }
.dropdown-content { display: none; position: absolute; background-color: darkred; min-width: 160px;box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1 }
.dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block }
.dropdown-content a:hover { background-color: #ddd }
.dropdown:hover .dropdown-content { display: block }
.dropdown:hover .dropbtn { background-color: black }
html, body { height: 100%; background: #842024 }
}
Any help is really appreciated!
Thanks,
Ryan