how to handle multipart/form-data in node.js - forms

I am uploading image file from client side using multipart form data. I want to receieve and write it as a file in the server side using node.js.
<html>
<body>
<form action="url" method="post" enctype="multipart/form-data">
<input type="text" name="imageName">
<input type="file" name="sam">
</form>
</body>
</html>
This is my client side code. How to handle this file in server side.

It is repeated question below link.
Uploading images using Node.js, Express, and Mongoose
Here is example:
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, form = require('connect-form');
var app = express.createServer(
// connect-form (http://github.com/visionmedia/connect-form)
// middleware uses the formidable middleware to parse urlencoded
// and multipart form data
form({ keepExtensions: true })
);
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
// connect-form adds the req.form object
// we can (optionally) define onComplete, passing
// the exception (if any) fields parsed, and files parsed
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
console.log('\nuploaded %s to %s'
, files.image.filename
, files.image.path);
res.redirect('back');
}
});
// We can add listeners for several form
// events such as "progress"
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
app.listen(3000);
console.log('Express app started on port 3000');
If your question is not solve then please visit this link . This is a nice article about file uploading.

You can use request module for sending a multipart request. Here is the sample code:
var jsonUpload = { };
var formData = {
'file': fs.createReadStream(fileName),
'jsonUpload': JSON.stringify(jsonUpload)
};
var uploadOptions = {
"url": "https://upload/url",
"method": "POST",
"headers": {
"Authorization": "Bearer " + accessToken
},
"formData": formData
}
var req = request(uploadOptions, function(err, resp, body) {
if (err) {
console.log('Error ', err);
} else {
console.log('upload successful', body)
}
});

Related

How to create folders on SharePoint 2019 using REST calls via postman? Getting 403: Forbidden error

I am using the below call to create a folder on SharePoint2019:
POST http://<site>/_api/web/folders
{
"__metadata": {
"type": "SP.Folder"
},
"ServerRelativeUrl": "/Shared Documents/Folder"
}
But I am getting the following error:
403 Forbidden: The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again.
Please check if you have got the valid form digest value in your side.
For example, if the site url is http://sp/sites/dev/
Then do a Post Request to this url http://sp/sites/dev/_api/contextinfo
Then use this form digest value in Request Header:
Here is a sample request to create folder using Rest:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createFolder();
});
}
function createFolder() {
var folderName = $("#txtFolderName").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/folders";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.Folder' },
'ServerRelativeUrl': 'Shared Documents/' + folderName
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Folder created successfully !!!");
}
function onQueryFailed() {
alert('Error!');
}
</script>
<div>
<strong>Enter FolderName:</strong><br />
<input type="text" id="txtFolderName" /><br />
<input type="button" id="btnSubmit" value="Create Folder" />
</div>
<div id="divResults"></div>
Reference:
Some Help for Authorization Problems in SharePoint 2013 REST API

How to replace Angular2 Http to upload files?

The following code attempts to send a file from an Angular2 app. It always end-up in the REST API not being able to recognize the file in the request it is receiving. (Even if the content seams to be there !)
After spending hours searching StackOverflow and countless other online sources, i came to the conclusion that the most recent version of Angular2 Http module/service should now be capable of handling file uploads. (The fact that it wasn't able to do so in the past is just amazing !)
See this article or even this git sample.
If i am to use an external lib like ng2-file-upload, it needs to be able to replace Angular2::Http with as little modification as possible to the following code. (i.e. I cannot change the HTML form.)
Component.html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()" novalidate>
<label>Votre avatar !</label>
<input class="form-control" type="file" name="avatar" (change)="imageUpload($event)" >
Component.ts
imageUpload(e) {
let reader = new FileReader();
//get the selected file from event
let file = e.target.files[0];
reader.onloadend = () => {
this.image = reader.result;
}
reader.readAsDataURL(file);
}
onSubmit() {
if (this.image){
this.authService.setAvatar(this.image).subscribe(
d => {
//Do Nothing... Will navigate to this.router.url anyway so...
},
err =>{
this.errorMessage = err;
console.log(err);
}
);
}
}
authService.ts
setAvatar(image:any){
let form: FormData = new FormData();
form.append('avatar', image);
return this.http.post (Config.REST_URL + 'user/setAvatar?token=' +localStorage.getItem('token'), form,
{headers: new Headers({'X-Requested-With': 'XMLHttpRequest' })}
).catch(this.handleError);
}
REST_API Php (LARAVEL)
public function setAvatar(Request $request){
if($request->hasFile("avatar")) { // ALWAYS FALSE !!!!
$avatar = $request->file("avatar");
$filename = time() . "." . $avatar->getClientOriginalExtension();
Image::make($avatar)->fit(300)->save(public_path("/uploads/avatars/" . $filename));
return response()->json(['message' => "Avatar added !"], 200);
}
return response()->json(['message' => "Error_setAvatar: No file provided !"], 200);
}
Content of the Request Payload (As seen from Chrome Inspect/Network)
------WebKitFormBoundary8BxyBbDYFTYpOyDP
Content-Disposition: form-data; name="avatar"
Should be more like...:
Content-Disposition: form-data; name="avatar"; filename="vlc926.png"
Content-Type: image/png
Turns out Angular2's Http can now send files... And it's super easy !.... I just can't believe there are just no documentation out there showing this !
Except this one. (Credits to MICHAƁ DYMEL)
The HTML
<input #fileInput type="file"/>
<button (click)="addFile()">Add</button>
Component.ts
#ViewChild("fileInput") fileInput;
addFile(): void {
let fi = this.fileInput.nativeElement;
if (fi.files && fi.files[0]) {
let fileToUpload = fi.files[0];
this.uploadService
.upload(fileToUpload)
.subscribe(res => {
console.log(res);
});
}
}
The service.ts
upload(fileToUpload: any) {
let input = new FormData();
input.append("file", fileToUpload);
return this.http.post("/api/uploadFile", input);
}

Sending images with AngularJS and NodeJS

Hi I am making a service to send images with users' information. For example, name, phone number, and their images to upload.
I am planning to use ng-file-upload, one of AngularJS custom dependency. And then, I am going to use Nodemailer to send all the information and images to somewhere else.
But my question is can I send other text data along with ng-file-upload? And second is can I send images with other text data through nodemailer?
Although OP has found a solution in the end, since I had the same problem I figured I'd post the whole code here for others who might struggle with that.
So here is how I combined ng-file-upload and nodemailer to upload and send attachments by e-mail using Gmail:
HTML form:
<form name="postForm" ng-submit="postArt()">
...
<input type="file" ngf-select ng-model="picFile" name="file" ngf-max-size="20MB">
...
</form>
Controller:
app.controller('ArtCtrl', ['$scope', 'Upload', function ($scope, Upload) {
$scope.postArt = function() {
var file = $scope.picFile;
console.log(file);
file.upload = Upload.upload({
url: '/api/newart/',
data: {
username: $scope.username,
email: $scope.email,
comment: $scope.comment,
file: file
}
});
}
}]);
Server:
var nodemailer = require('nodemailer');
var multipartyMiddleware = require('connect-multiparty')();
// multiparty is required to be able to access req.body.files !
app.mailTransporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: ...
pass: ...
},
tls: { rejectUnauthorized: false } // needed or Gmail might block your mails
});
app.post('/api/newart', multipartyMiddleware,function(req,res){
console.log(req.files);
mailOptions = {
from: req.body.email,
to: ...,
subject: ...
text: ...,
attachments: [{
filename: req.files.file.name,
path: req.files.file.path // 'path' will stream from the corresponding path
}]
};
app.mailTransporter.sendMail(mailOptions, function(err) {
if (err) {
console.log(err);
res.status(500).end();
}
console.log('Mail sent successfully');
res.status(200).end()
});
});
The nodemailer examples helped me figure this out!
This works for any file type. The key aspect that some people might miss out is that you need multiparty to access the uploaded file (in req.body.files). Then the most convenient way to attach it is using the path key in the attachment object.
Definitely you can send images as attachment using nodemailer.
Try this for sending image as an attachment :
var mailOptions = {
...
html: 'Embedded image: <img src="cid:unique#kreata.ee"/>',
attachments: [{
filename: 'image.png',
path: '/path/to/file',
cid: 'unique#kreata.ee' //same cid value as in the html img src
}]
}
For more reference on sending image as attachment go through nodemailer's "using Embedded documentation".
For the first part of the question:
Yes! you can send other text data along with image using ng-file-upload. It depends how you want to do it and what you want to achieve.
For example, see the code below:
HTML Template
<form name="form">
<input type="text" ng-model="name" ng-required="true">
<input type="text" ng-model="phoneNo" ng-required="true">
<div class="button" ngf-select ng-model="file" name="file" ngf-pattern="'image/*'" ngf-accept="'image/*'" ngf-max-size="20MB" ngf-min-height="100" ngf-resize="{width: 100, height: 100}">Select</div>
<button type="submit" ng-click="submit()">submit</button>
</form>
Controller
$scope.submit = function() {
if ($scope.form.file.$valid && $scope.file) {
$scope.upload($scope.file);
}
};
// upload on file select or drop
$scope.upload = function (file) {
Upload.upload({
url: 'upload/url',
data: {file: file, 'name': $scope.name, 'phoneNo' : $scope.phoneNo}
}).then(function (resp) {
console.log('Success ' + resp.config.data.file.name + 'uploaded. Response: ' + resp.data);
}, function (resp) {
console.log('Error status: ' + resp.status);
}, function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name);
});
};
Read ng-file-upload documentation completely to see understand all the things you can do along with file upload. It has many examples to make you understand everything.
I hope it helps, and answer your question.

upload a file using angular, express and mongodb's gridfs

I am new to these technologies and hence have limited knowledge on how to upload a file. During my research, I have seen ngUpload and other javascript/directive based solutions. However, I am trying the following and not sure what else I am missing to complete it.
I am trying to upload file after creating a blog using angular-express-blog application. I have the following code
In view.jade
fieldset
h5 Add Media
form(name='theForm', enctype="multipart/form-data")
.clearfix
label Document Name
.input: input(ng-model='form.docName', name='docName', type='text')
.clearfix
label File
.input: input(ng-model='form.file', type="file", name="file")
.actions
button(ng-click="uploadFiles('/page3files')") Upload Files
the controller, I do need to return to the uploadfile page hence, I am passing in /page3files.
$scope.uploadFiles = function( path ) {
//alert("upload files clikced");
$http.post('/api/uploadFile', $scope.form).
success(function(data) {
$scope.form.docName='';
$scope.form.file='';
$location.path(path);
});
};
In the express routes file
exports.uploadFile = function (req, res) {
console.log("doc name: " + req.body.docName);
console.log("file name: " + req.body.file.name);
console.log("file path: " + req.body.file.path);
res.json(true);
};
Unfortunately, I am getting an exception at req.body.file.name saying cannot read property 'name' of undefined.
Any assistance is much appreciated.
Thanks,
Melroy
for the $http.post() to be able to upload files you need to set some configurations.
headers : {'Content-Type': undefined},
transformRequest: angular.identity
You can use the simple/lightweight angular-file-upload directive that takes care of that for you.
It supports drag&drop, file progress and file upload for non-HTML5 browsers with FileAPI flash shim.
<div ng-controller="MyCtrl">
<input type="file" ng-file-select="onFileSelect($files)" multiple>
</div>
JS:
//inject angular file upload directive.
angular.module('myApp', ['angularFileUpload']);
var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
$scope.onFileSelect = function($files) {
//$files: an array of files selected, each file has name, size, and type.
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
$upload.upload({
url: 'my/upload/url',
file: $file,
progress: function(e){}
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}
}
}];
There are more info on the README page and there is a Demo page
You can send file data with FormData object. For Example:
HTML:
<fieldset>
<legend>Upload Video</legend>
<input type="file" name="photo" id="photo">
<input type="button" ng-click="uploadVideo()" value="Upload">
</fieldset>
JS:
$scope.uploadVideo = function () {
var photo = document.getElementById("photo");
var file = photo.files[0];
var fd = new FormData(); //Create FormData object
fd.append('file', file);
$http.post('/uploadVideo', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function (data) {
// Do your work
});
};

Nodejs POST request multipart/form-data

I am trying to upload a photo via a POST request with the request module
According to the readme I should just be able to do this
var r = request.post("http://posttestserver.com/post.php", requestCallback)
var form = r.form()
form.append("folder_id", "0");
form.append("filename", fs.createReadStream(path.join(__dirname, "image.png")));
function requestCallback(err, res, body) {
console.log(body);
}
The problem is, this doesn't work. I get a reply from the test server saying it dumped 0 post variables.
I have confirmed that the server is in working condition with this little html page
<html>
<body>
<form action="http://posttestserver.com/post.php?dir=example" method="post" enctype="multipart/form-data">
File: <input type="file" name="submitted">
<input type="hidden" name="someParam" value="someValue"/>
<input type="submit" value="send">
</form>
</body>
</html>
So the question is, what am I doing wrong with the request module? Is there a better way to send multipart/form-data with node?
After some more research, I decided to use the restler module. It makes the multipart upload really easy.
fs.stat("image.jpg", function(err, stats) {
restler.post("http://posttestserver.com/post.php", {
multipart: true,
data: {
"folder_id": "0",
"filename": restler.file("image.jpg", null, stats.size, null, "image/jpg")
}
}).on("complete", function(data) {
console.log(data);
});
});
So I just got done wrestling with this myself and here is what I learned:
It turns out that neither request or form-data are setting the content-length header for the generated body stream.
Here is the reported issue: https://github.com/mikeal/request/issues/316
The solution posted by #lildemon gets around this by:
Generating the FormData object
Getting it's length
Making the request and setting the form object and content-length header explicitly
Here is a modified version of your example:
var request = require('request');
var FormData = require('form-data');
var form = new FormData();
form.append("folder_id", "0");
form.append("filename", fs.createReadStream(path.join(__dirname, "image.png")));
form.getLength(function(err, length){
if (err) {
return requestCallback(err);
}
var r = request.post("http://posttestserver.com/post.php", requestCallback);
r._form = form;
r.setHeader('content-length', length);
});
function requestCallback(err, res, body) {
console.log(body);
}
I have working code that does exactly what your question states, with one exception. My file content is appended this way:
form.append('file', new Buffer(...),
{contentType: 'image/jpeg', filename: 'x.jpg'});
To discover the final options argument I had to drill down into the source of form-data. But this gives me a working configuration. (Maybe it was what you were missing, but of course that will depend on the server.)
I tried also request and form-data modules and was unable to upload a file.
You can use superagent which works:
http://visionmedia.github.io/superagent/#multipart-requests.
var request = require('superagent');
var agent1 = request.agent();
agent1.post('url/fileUpload')
.attach('file',__dirname + "/test.png")
.end(function(err, res) {
if (err) {
console.log(err)
}
});
Try request module. It works like any other normal post request
var jsonUpload = { };
var formData = {
'file': fs.createReadStream(fileName),
'jsonUpload': JSON.stringify(jsonUpload)
};
var uploadOptions = {
"url": "https://upload/url",
"method": "POST",
"headers": {
"Authorization": "Bearer " + accessToken
},
"formData": formData
}
var req = request(uploadOptions, function(err, resp, body) {
if (err) {
console.log('Error ', err);
} else {
console.log('upload successful', body)
}
});