I currently have the following AJAX POST request sending the FormData() of the loaded file.
It takes in however many files uploaded, places them into a new form, and then posts that form as data to the /api/file URL
$('#file').on('change', function(){
var files = $(this).get(0).files;
$('#file').ready(function(){
if (files.length > 0){
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
console.log(file);
var tmppath = URL.createObjectURL(event.target.files[0]);
formData.append('userFile', tmppath);
}
$.ajax({
url: '/api/file',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
console.log('upload successful!\n' + data);
document.getElementById('ipfs').href = 'https://ipfs.infura.io/ipfs/' + data;
document.getElementById('ipfs').innerHTML = data;
},
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
percentComplete = parseInt(percentComplete * 100);
$('.progress-bar').text(percentComplete + '%');
$('.progress-bar').width(percentComplete + '%');
if (percentComplete === 100) {
$('.progress-bar').html('Done');
}
}
}, false);
return xhr;
}
});
}
});
and the following express node app
app.post('/api/file', async function(req,res){
console.log(await req.files);
});
And all it prints out is Null.
Related
I'm using summernote for my text editor.
I was making image upload function by using multer.
This is my summernote function.
onImageUpload : function(files, editor, welEditable){
// 파일 업로드(다중업로드를 위해 반복문 사용)
for (var i = files.length - 1; i >= 0; i--) {
sendFile(files[i], editor, welEditable);
}
}
and this is sendFile function
function sendFile(file, editor, welEditable){
console.log(file)
data = new FormData();
data.append("file", file);
$.ajax({
data: data,
type: "POST",
url: "/post/img",
cache: false,
contentType: false,
processData: false,
success: function(url) {
console.log(url)
editor.insertImage(welEditable, url);
}
});
}
Console shows file data normally, but
url: "/post/img" doesn't work well
Just in case, my post/img router code is like
router.post("/img", upload.array("note-dialog-image-file-16755274670761", 4), (req, res) => {
console.log("파일 이름 : ", req.files);
let urlArr = new Array();
for (let i = 0; i < req.files.length; i++) {
urlArr.push(`/img/${req.files[i].filename}`);
console.log(urlArr[i]);
}
let jsonUrl = JSON.stringify(urlArr);
res.json(jsonUrl);
});
In the multer middleware definition change the field name
router.post("/img", upload.array("note_dialog_image_file"), (req, res) => {
console.log("파일 이름 : ", req.files);
let urlArr = new Array();
for (let i = 0; i < req.files.length; i++) {
urlArr.push(`/img/${req.files[i].filename}`);
console.log(urlArr[i]);
}
let jsonUrl = JSON.stringify(urlArr);
res.json(jsonUrl);
});
and in the UI the FormData has to be changed, so that the file is pointed with correct field name
data = new FormData();
data.append("note_dialog_image_file", file);
I using that API to create resumable Upload in Drive.
It worked but i can't receive response data from Promise
Here is my code:
var fs = require('fs');
var request = require('request');
var mime = require('mime');
var _ = require("underscore");
class resumableUpload {
constructor(credentials,token,options={}){
this.credentials = credentials; // object from json credentials
this.token = token; // object from token credentials
this.new_token = {};
this.expiry_token_time = 0;
this.options = Object.assign({
size:256*1024,
retry:-1
},options)
}
refresh_token(){
return new Promise((ok,faild)=>{
var now = new Date().getTime();
if(now>this.expiry_token_time){
request.post("https://www.googleapis.com/oauth2/v4/token",{
form:{
refresh_token:this.token.refresh_token,
client_id:this.credentials.client_id,
client_secret:this.credentials.client_secret,
redirect_uri:this.credentials.redirect_uris[0],
grant_type:'refresh_token'
}
},(err,httpResponse,body)=>{
if(err) faild(err);
this.new_token = JSON.parse(body);
this.expiry_token_time = now + this.new_token.expires_in*1000;
ok(this.new_token.access_token);
})
}else{
ok(this.new_token.access_token);
}
})
}
/*
Upload Resumable
file:{
name:'name of file',
path:'path/to/file'
}
*/
upload(file){
return new Promise((ok,faild)=>{
this.refresh_token().then((access_token)=>{
console.log(access_token);
this.file_len = fs.statSync(file.path).size;
var form = {};
if(!_.isEmpty(file.name)) form.name = file.name;
if(!_.isEmpty(file.parents)) form.parents = [file.parents];
request.post({
uri:'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable',
headers:{
'Authorization':`Bearer ${access_token}`,
'Content-Type':'application/json; charset=UTF-8',
'X-Upload-Content-Type':mime.getType(file.path),
'X-Upload-Content-Length': this.file_len,
'Content-Length':new Buffer(JSON.stringify(form)).length
},
body:JSON.stringify(form)
},(err,res,body)=>{
if(err || _.isEmpty(res.headers.location)){
if ((this.retry > 0) || (this.retry <= -1)) {
this.retry--;
return this.upload(file); // retry
} else {
//console.log(body);
faild("Over retry");
}
}else{
var location = res.headers.location;
//console.log("URL UPLOAD: ",location);
this.sendUpload(location,file).then((data)=>{
console.log("UPLOAD DONE!!!");
ok(data);
}).catch((err)=>{
console.log("ERROR: ",err);
faild(err);
});
}
})
}).catch(faild)
})
}
sendUpload(api,file,start=0){
return new Promise((ok,faild)=>{
this.refresh_token().then((access_token)=>{
var end = parseInt(start+this.options.size-1);
if(start>=this.file_len) ok("DONE");
if(end>=this.file_len) end = this.file_len - 1;
var headers = {
'Authorization':`Bearer ${access_token}`,
'Content-Length': parseInt(end - start + 1),
'Content-Range':`bytes ${start}-${end}/${this.file_len}`
}
var uploadPipe = fs.createReadStream(file.path, {
start: start,
end: end
})
uploadPipe.pipe(request.put({uri:api,headers:headers}).on('response',(res)=>{
if(res.statusCode == 308){
//console.log(res.headers);
var new_start = parseInt(res.headers.range.split('-')[1]);
console.log("Percent: "+(new_start/this.file_len*100).toFixed(2)+" %");
return this.sendUpload(api,file,new_start+1);
}else if(res.statusCode == 200 || res.statusCode == 201){
console.log("percent: 100 %");
//ok({status:"OK"});
}
}).on('error',(err)=>{
if ((this.retry > 0) || (this.retry <= -1)) {
this.retry--;
console.log("Retry Again");
return this.sendUpload(api,file,start);
}else{
faild("Over retry");
}
}).on('data',(data)=>{
if(!_.isEmpty(data)){
console.log(data.toString());
ok(data.toString());
}
}))
}).catch(faild)
})
}
}
module.exports = resumableUpload;
In that code - sendUpload function, I split my file to many chunk and upload it in to drive.
when I upload the last chunk, server will response statusCode is 200 or 201.
It console.log "percent: 100 %" and received data from that response.
My data of response like it:
{
"kind": "drive#file",
"id": "xxxxxxxxxxxxxxxxxxxxxxxxx",
"name": "test-video",
"mimeType": "video/mp4"
}
But, the Resolve (ok function) not call, cause in upload function, i can't receive it in then function. it mean i can't see "UPLOAD DONE!!!" in screen.
Resloved: Thanks for Roamer-1888
In Pipe, return a promise not work. I change return this.sendUpload(...) to this.sendUpload(...).then(ok,faild) and it worked.
I'm uploading video file from local to server and then I'll be uploading it to cdn,
the issue i'm facing is my code is running well on local but its not working when i patch it to server.
Here is my code
commonJs
$("#uploadVideo").click(function (e) {
var reader = new FileReader();
var fileInput = document.getElementById('Videofile');
var previewUrl = window.URL.createObjectURL(fileInput.files[0]);
$(".video").attr("src", previewUrl);
var videotype = "video/mp4";
var file_data = $("#Videofile").prop("files")[0];
if (!file_data.type.match(videotype)) {
return "alert('Please upload mp4 files')"
} else {
var metadata = {
'content-type': 'video/mp4',
'size': file_data.size,
'uploaded': new Date(),
}
reader.onload = function (e) {
$("file_data").text("File Content: " + reader.result); // Show the file content
}
reader.readAsBinaryString(file_data);
file_data.onloadedmetadata = function () {
alert("Meta data for audio loaded");
};
};
var form_data = new FormData();
form_data.append("file", file_data)
form_data.append("metdata", metadata)
for (var key of form_data.entries()) {
console.log(key[0] + ', ' + key[1]);
}
if (form_data != undefined) {
$.ajax({
type: "post",
contentType: false,
processData: false,
url: "/api/recordvideo",
data: form_data,
dataType: 'json',
success: function (result) {
if (result) {
$(".video").attr("src", result.videolink);
alert("Successfully Uploaded Video");
console.log("Successfully Uploaded Video");
} else {
alert("Error on Uploading Video");
console.log("Error on Uploading Video");
}
},
error: function (err) {
console.log("error");
}
});
}
e.preventDefault();
e.stopPropagation();
});
ServerSide
app.post('/api/recordvideo',Api.recordvideo);
var Upload = require('gcs-resumable-upload');
ApiService.recordvideo = function (req, res) {
var db = req.db;
console.log("came in cloudupload");
var form = new formidable.IncomingForm();
var filesdata;
form.keepExtensions = true;
form.multiples = false;
form.on('fileBegin', function (name, file){
file.path = 'public/demo/' + file.name;
console.log("fileBegin: " + JSON.stringify(file));
});
form.on('file', function (name, file){
console.log('Uploaded ' + JSON.stringify(file));
var path = file.path;
console.log("came in cloud3 :" + JSON.stringify(path));
});
form.parse(req, function (err, fields, files) {
console.log("came in cloud0" + JSON.stringify(files));
filesdata = files;
});
console.log("came in cloud2");
form.on('end', function (fields, files) {
var userid = appconfig.ObjectID(appconfig.decrypt(req.signedCookies['gid']));
var path = this.openedFiles[0].path;
console.log("came in cloud3 :" + JSON.stringify(path));
fs.createReadStream(path)
.pipe(Upload.upload({ bucket: '******', file: path, metadata: { contentType: this.openedFiles[0].type } }))
.on('finish', function (response) {
console.log("Successfully Uploaded Video :" + JSON.stringify(response));
res.send({ "status": false, "videolink": "https://****/****/" + filesdata.file.name });
});
});
//res.send({ "status": false, "err": null });
}
At start atleast it was uploading to server folder & then in chrome developers tool it used to give response: {readystate : 4, . . . }
And now, I made some changes then it doesnt even hit my api, After few seconds it gives error in chrome developer tools 404() / 502 ()
Well, I got the solution, Previously I was using gcs-resumable-upload module to upload, but now I tried with '#google-cloud/storage' module through which I was able to upload upto 9mb.
const Storage = require('#google-cloud/storage');
var db = req.db;
console.log("came in cloudupload");
var form = new formidable.IncomingForm();
var filesdata;
form.keepExtensions = true;
form.multiples = false;
form.parse(req, function (err, fields, files) {
filesdata = files;
});
form.on('end', function (fields, files) {
var userid = appconfig.ObjectID(appconfig.decrypt(req.signedCookies['gid']));
var path = this.openedFiles[0].path;
const storage = new Storage({
keyFilename: 'gcloudcred.json'
});
const myBucket = storage.bucket('onfvideo');
myBucket.upload(path).then((resp) => {
console.log('uploaded to' + resp);
res.send({ "status": true, "err": null });
}).catch(err => {
console.error('ERROR:', err);
res.send({ "status": false, "err": null });
});
});
};
The Limitation of 9mb I was facing due to .netframework data-transfer limit which i was able to resolve using
<system.web>
<customErrors mode="Off"/>
<httpRuntime targetFramework="4.5" maxRequestLength="7483648" />
</system.web>
Method 2: Using xhr calling RestApi
1. Generated Access token using google-auto-auth module
2. XMLHttpRequest
var fileInput = $("#Videofile").prop("files")[0];
var url = "https://www.googleapis.com/upload/storage/v1/b/bucketname/o?uploadType=media&name=" + fileInput.name;
var http = new XMLHttpRequest();
http.open('POST', url, true);
http.setRequestHeader('Content-type', 'video/mp4');
http.setRequestHeader("Authorization", "Bearer " + token);
http.send(fileInput);
http.onprogress = function (ev) {
if (ev.lengthComputable) {
var percentage = Math.round((ev.loaded / ev.total) * 100);
console.log("percent " + percentage + '%');
}else {
console.log("Unable to compute progress information since the total size is unknown");
}
}
http.onloadstart = function (ev) {console.log("start")}
http.onloadend = function (ev) {}
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
var response = JSON.parse(http.responseText);
alert("Successfully Uploaded Video");
}
}
I want to check the percentage of file uploading in the third server.
below is my controller code.
which upload the file to third server.
BASE.APP.post('/uploadFile/:request/:file', function (req, res, next) {
//var form = new BASE.multiparty.Form();
var path = 'uploads/'+req.params.file;
var fstream = BASE.FS.createReadStream(path);
//form.on('part', function(part) {
// console.log('inside');
var url = req.usersession.webipAddress;
/* var formData = {
file: {
value: BASE.FS.createReadStream(path),
options: {
fileNameUnique: req.params.file
}
}
};
// Post the file to the upload server
BASE.request.post({url: url+'test/service/uploadFile/', formData: formData});*/
/*var form = new BASE.FormData();
form.append('fileNameUnique', req.params.file);
form.append( 'file',fstream);
*/
var formData = {
fileNameUnique: req.params.file,
file: fstream
};
var r = BASE.request.post({url: url+'test/service/uploadFile/', formData: formData}, function(err1, res1, body){
console.log('new method err' + err1);
console.log('new method' + res1);
clearInterval(tasktimeoutId);
tasktimeoutId = false;
res.send(res1);
});
var tasktimeoutId = null;
if(!tasktimeoutId){
tasktimeoutId = setInterval(function(){
console.log('interval inside');
interrupttable.findOne({ "filename": req.params.file }, function(err, thor) {
if (thor!=null)
{
console.log('null inside');
if(thor.status=='interrupt')
{
console.log('interrupt');
r.abort();
r = null;
clearInterval(tasktimeoutId);
tasktimeoutId = false;
res.send("interrupted");
//return
//next(err);
}
}
});
}, 1000);
}
});
is there any way to check the file progress in percentage. So that i can
show the progress bar in front end.
Check this repo: https://github.com/zeMirco/express-upload-progress. It should have what you are looking for :)
I'm sorry about my English. I am use MEAN stack for writting my app. I find out some modules for uploading image and angular-file-upload is my choice. But when I upload the image the percent show on console completed. I'm check upload directory. The file is uploaded but can not read in Image Viever.
Here my code on angular :
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
url: '/posts/upload/',
method: 'POST',
file: file,
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}
};
Here my code on Node JS :
exports.upload = function(req, res) {
var data = new Buffer('');
req.on('data', function(chunk) {
data = Buffer.concat([data, chunk]);
});
req.on('end', function() {
req.rawBody = data;
fs.writeFile(config.root + path.sep + 'public/upload' + path.sep + uuid.v1(), data ,function(err){
if(err) throw err;
console.log('ok saved')
});
res.send('ok');
});
}
I guess I do something wrong with Node but I can't find out it. Please tell me what my mistake.
You need to send the preview url for the uploaded image back to angular.
On server side
req.on('end', function() {
req.rawBody = data;
var imgUrl = '/upload' + path.sep + uuid.v1();
fs.writeFile(config.root + path.sep + 'public' + imgUrl, data ,function(err){
if(err) throw err;
//send back the preview url
res.jsonp({
imgUrl: imgUrl
})
});
Client Side
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
url: '/posts/upload/',
method: 'POST',
file: file,
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
$scope.imgurl = data.imgUrl;
});
}
};
You can display image like this
<img ng-src="{{imgurl}}" ng-show="imgurl" alt="preview for uploaded image" >