I'm using sails.js as my backend with bluebird promise, I tried to upload file using req.file.upload, the callback way works just fine and the file gets uploaded:
req.file('file').upload({
maxBytes: 2000000,
dirname: 'uploadFolder'
}, function (err, files) {
if (err) {
return res.serverError(err);
}
return res.ok();
}
But the promise way does not:
var Promise = require('bluebird');
var fileUploader = Promise.promisify(req.file('file').upload);
fileUploader({
maxBytes: 2000000,
dirname: currentUploadFolder
}).then(function(files) {
console.log(files);
return Promise.resolve(files);
}).catch(function(err) {
console.log(err);
return Promise.reject(err);
});
File doesn't get uploaded and the console keeps complaining:
data: app.js:1800 - [TypeError: Cannot read property 'length' of undefined]
Any thoughts please?
This case is unique and you can't use promisify here. You need to create new Promise and return it.
return new Promise(function(resolve, reject) {
req.file('file').upload({
maxBytes: 2000000,
dirname: 'uploadFolder'
}, function (error, files) {
return error ? reject(error) : resolve(files);
}
});
You can move it to helper\services\whatever and got something like this
// api/services/UploadService.js
module.exports = {
uploadFile: function(req) {
return new Promise(function(resolve, reject) {
req.file('file').upload({
maxBytes: 2000000,
dirname: 'uploadFolder'
}, function (error, files) {
return error ? reject(error) : resolve(files);
}
});
}
};
// api/controllers/AnyController.js
module.exports = {
upload: function(req, res) {
UploadService
.uploadFile(req)
.then(res.ok)
.catch(res.negotiate);
}
};
Related
I'm trying to develop an app where users can can video call to each other and share their screens using WebRTC technology. I have succeed with either video call or screen sharing app and now I'm trying to make it to be able to switch between getUserMedia and getDisplayMedia on button click during a call inside the same RTCPeerConnection but it doesn't work.
This is how I thought it could work:
function onLogin(success) {
var configuration = { offerToReceiveAudio: true, offerToReceiveVideo: true, "iceServers" : [ { "url" : "stun:stun.1.google.com:19302" } ] };
myConnection = window.RTCPeerConnection ? new RTCPeerConnection(configuration, { optional: [] }) : new RTCPeerConnection(configuration, { optional: [] });
myConnection.onicecandidate = function (event) {
console.log("onicecandidate");
if (event.candidate) send({ type: "candidate", candidate: event.candidate });
};
myConnection.ontrack=function(e){
try{remoteVideo.src = window.webkitURL?window.webkitURL.createObjectURL(e.streams[0]):window.URL.createObjectURL(e.streams[0])}
catch(err){remoteVideo.srcObject=e.streams[0]}
}
myConnection.ondatachannel=openDataChannel
openDataChannel();
startAVStream();
//startSStream()
};
function startAVStream(enable){
if(sStream)sStream.getTracks().forEach( function (track) {
try{myConnection.removeTrack( track, sStream );}
catch(e){}
} );
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(s => {
if(!avStream){
avStream = s;
avStream.getTracks().forEach( function (track) {
myConnection.addTrack( track, avStream );
} );
}
}, function (error) { console.log(error); });
}
function startSStream(enable){
if(avStream)avStream.getTracks().forEach( function (track) {
try{myConnection.removeTrack( track, avStream );}
catch(e){}
} );
navigator.mediaDevices.getDisplayMedia({ video: true }).then(s => {
if(!sStream){
sStream = s;
sStream.getTracks().forEach( function (track) {
myConnection.addTrack( track, sStream );
} );
}
}, function (error) { console.log(error); });
}
Can anyone tell me how I can switch between tracks inside the same RTCPeerConnection or should I create 2 separate RTCPeerConnection - one for video/audio streaming and another for screen sharing?
Any help appreciated! Thanks!
You could use RTCRtpSender.replaceTrack to splice the screen capture track. This doesn't require renegotiation, and therefore has very low latency.
let newstream = navigator.mediaDevices.getDisplayMedia({});
let newtrack = newstream.getTracks()[1];
if(newtrack.kind !== 'video')
throw new Error('Eek!?');
pc.getSenders().forEach(async s => {
if(s.track && s.track.kind === 'video')
await s.replaceTrack(newtrack);
});
The test for s.track not being null deals with the case where you previously called replaceTrack(..., null).
shareScreen = () =>{
const success = (stream) => {
window.localStream = stream
// this.localVideoref.current.srcObject = stream
// localStream.replaceStream(stream);
this.setState({
localStream: stream
})
Object.values(this.state.peerConnections).forEach(pc => {
pc.getSenders().forEach(async s => {
console.log("s.track ",s.track);
if(s.track && s.track.kind === 'video'){
stream.getTracks().forEach(track => {
// pc.addTrack(track, this.state.localStream)
s.replaceTrack(track);
});
}
});
});
}
const failure = (e) => {
console.log('getUserMedia Error: ', e)
}
navigator.mediaDevices.getDisplayMedia({ cursor: true }).then(success).catch(failure)}
I'm currently running some tests with postman where I get a schema and try to validate my results against it.
I know the schema is not consistent with the response I'm getting but I wanted to know how is it possible to expand the results to give a bit more information.
so for example if I have a request like this:
GET /OBJ/{ID}
it just fails with the feedback:
Schema is valid:
expected false to be true
I was hoping to manage to get a bit more feedback in my newman report
this is an example of my test:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// only preform tests if response is successful
if (pm.response.code === 200) {
var jsonData = pm.response.json();
pm.test("Data element contains an id", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).eql(pm.environment.get("obj_id"));
});
pm.test('Schema is valid', function() {
pm.expect(tv4.validate(jsonData, pm.globals.get("objSchema"))).to.be.true;
});
}
and this is how I run my tests:
const newman = require('newman');
newman.run({
insecure: true,
collection: require('../resources/API.postman_collection.json'),
environment: require('../resources/API.postman_environment.json'),
reporters: 'htmlextra',
reporter: {
htmlextra: {
export: './build/newman_report.html',
logs: true,
showOnlyFails: false,
darkTheme: false
}
}
}, function (err) {
if (err) {
throw err;
}
console.log('collection run complete!');
});
is there a way I can get more information about the validation failure?
I tried a few quick google search but have not come up to nothing that seemed meaningful
it's not exactly what I wanted but I managed to fix it with something like this:
// pre-check
var schemaUrl = pm.environment.get("ocSpecHost") + "type.schema";
pm.sendRequest(schemaUrl, function (err, response) {
pm.globals.set("rspSchema", response.json());
});
// test
var basicCheck = () => {
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200);
});
};
// create an error to get the output from the item validation
var outputItemError = (err) => {
pm.test(`${err.schemaPath} ${err.dataPath}: ${err.message}`, function () {
pm.expect(true).to.be.false; // just output the error
});
};
var itemCheck = (item, allErrors) => {
pm.test("Element contains an id", function () {
pm.expect(item.id).not.eql(undefined);
});
var Ajv = require('ajv');
ajv = new Ajv({
allErrors: allErrors,
logger: console
});
var valid = ajv.validate(pm.globals.get("rspSchema"), item);
if (valid) {
pm.test("Item is valid against schema", function () {
pm.expect(valid).to.be.true; // just to output that schema was validated
});
} else {
ajv.errors.forEach(err => outputItemError(err));
}
};
// check for individual response
var individualCheck = (allErrors) => {
// need to use eval to run this section
basicCheck();
// only preform tests if response is successful
if (pm.response.code === 200) {
var jsonData = pm.response.json();
pm.test("ID is expected ID", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).eql(pm.environment.get("nextItemId"));
});
itemCheck(jsonData, allErrors);
}
}
individualCheck(true);
just create a function to do an item test where I do a stupid assert.false to output each individual error in the schema path
I am using react-native-fs to download files from server and save them. Once they are downloaded I am using react-native-file-viewer to open them. This process totally works fine: I am able to download and open it in the viewer, but I am not able to save the file in the File application from the viewer, though I can save in iCloud but not in the iPhone.
The downloaded file is stored in a place like
/var/mobile/Containers/Data/Application/CCF6CD16-A62A-48BB-92F3-3021195CFE0C/Documents/react-native-pdf.pdf
but this is not shown in the File app.
The code I am using to download and view the file is as follows
RNFS.downloadFile({
fromUrl: 'http://www.mywebsite.com/react-native-pdfurl.pdf',
toFile: `${RNFS.DocumentDirectoryPath}/react-native-pdfurl.pdf`,
}).promise.then((r) => {
console.log('yo yo yo ');
this.setState({ isDone: true });
const path = `${RNFS.DocumentDirectoryPath}/react-native-pdfurl.pdf`;
FileViewer.open(path)
.then(() => {
// success
})
.catch(error => {
// error
});
RNFS.readDir(RNFS.DocumentDirectoryPath).then(files => {
console.log(files);
})
.catch(err => {
console.log(err.message, err.code);
});
});
The readDir gets me the name path of the file saved. But this is not reflected in any folder in the File application.
My question is how can I save the file in a way that it shows in the File application.
The below code downloads the file and opens it. In case the file already exists it will directly open it.
downloadOpenClick = async (item) => {
try {
let platformName = 'ios';
if (Platform.OS === 'ios'){
platformName = 'ios';
}else{
platformName = 'android';
}
const selectedFile = item;
var dirType=null;
if(Platform.OS === 'ios'){
dirType = RNFS.DocumentDirectoryPath;
}else{
await this.requestStoragePermission();
dirType = RNFS.ExternalStorageDirectoryPath+'/AppName';
}
RNFS.mkdir(dirType+`/Folder`).then(files => {
RNFS.mkdir(dirType+`/Folder/SubFolder`).then(files => {
//console.log(files);
}).catch(err => {
//console.log(err.message, err.code);
});
}).catch(err => {
//console.log(err.message, err.code);
});
var exists = false;
RNFS.exists(`${dirType}/Folder/SubFolder/${selectedFile}`).then( (output) => {
if (output) {
exists = true;
const path = `${dirType}/Folder/SubFolder/${selectedFile}`;
FileViewer.open(path)
.then(() => {
// success
})
.catch(error => {
// error
console.log('error');
console.log(error);
});
} else {
const selectedFileUrl = selectedFile.replace(/\s/g, '%20');
RNFS.downloadFile({
fromUrl: `https://mywebsite/api/getAttachment?selectedFile=${selectedFileUrl}`,
toFile: `${dirType}/Folder/SubFolder/${selectedFile}`,
background: true,
begin: (res) => {
console.log(res);
this.setState({ contentLength: res.contentLength});
},
progress: (res) => {
this.setState({ showSpinner: true });
var prog = res.bytesWritten/res.contentLength
this.setState({ downloaded : prog});
console.log(this.state.downloaded);
}
}).promise.then((r) => {
//console.log(r);
this.setState({ showSpinner: false });
this.setState({ downloaded : 0});
const path = `${dirType}/${tipoDesc}/${oggetto}/${selectedFile}`;
FileViewer.open(path)
.then(() => {
// success
})
.catch(error => {
// error
console.log('error');
console.log(error);
});
}).catch(error => {
console.log('error');
console.log(error);
});;
}
});
} catch (error) {
console.log('error');
console.log(error);
}
};
using
react-native-file-viewer and react-native-fs
I am trying to use batch request for sending http post to the server.
The code snippet, which generate the request:
_.each(aNewDates, function (oNew) {
oModel.create("/CostCenterCalendarSet", oNew, {
groupId: "newDates"
});
});
oModel.setDeferredGroups(["newDates"]);
and the submit method:
oModel.submitChanges({
groupId: "newDates",
oSuccess: function (oMsg) {
return observer.next(oMsg);
},
oError: function (oErr) {
return observer.error(oErr);
},
});
as response I've got following error:
What am I doing wrong?
Update
I tried with ODataModel read method and does not get any result.
let oPlantFilter = new sap.ui.model.Filter("Plant", sap.ui.model.FilterOperator.EQ, oSelectedData.sPlant);
let oWcFilter = new sap.ui.model.Filter("WorkCenter", sap.ui.model.FilterOperator.EQ, oSelectedData.sWc);
oModel.read("/CostCenterCalendarSet", {
groupId: "query-dates",
filters: [oPlantFilter, oWcFilter]
});
oModel.setDeferredGroups(["query-dates"]);
return Rx.Observable.create(function (subscriber) {
oModel.submitChanges({
groupId: "query-dates",
success: function (oData, oResponse) {
return subscriber.next(oResponse);
},
error: function (oErr) {
return subscriber.error(oErr);
},
});
});
I use multer to do ajax upload in my project, and I use FormData in front-end to do ajax upload.
I am testing in my iPhone 5s
My Problem is when I click my input[type="file"], and I choose take picture, it can be successfully uploaded.
BUT when I choose from my gallery, and select a picture I took before, the upload program crashed
this problem will just cause in iPhone, but not in Android or PC
\routes\index.js:128
filename: req.file.path.replace(/public/, '')
^
TypeError: Cannot read property 'path' of undefined
at E:\GraduationProject\jnstagram\routes\index.js:128:23
at Array.<anonymous> (E:\GraduationProject\jnstagram\node_modules\multer\lib\make-middleware.js:52:37)
at listener (E:\GraduationProject\jnstagram\node_modules\on-finished\index.js:169:15)
at onFinish (E:\GraduationProject\jnstagram\node_modules\on-finished\index.js:100:5)
at callback (E:\GraduationProject\jnstagram\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (E:\GraduationProject\jnstagram\node_modules\ee-first\index.js:93:5)
at emitNone (events.js:80:13)
at IncomingMessage.emit (events.js:179:7)
at endReadableNT (_stream_readable.js:913:12)
at _combinedTickCallback (node.js:383:13)
at process._tickCallback (node.js:407:11)
my server side code:
var express = require('express');
var multer = require('multer');
var router = express.Router();
module.exports = function() {
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'public/uploads');
},
filename: function(req, file, cb) {
var name = file.originalname;
var dot = name.lastIndexOf('.');
cb(null, name.slice(0, dot) + '-' + new Date().getTime() + name.slice(dot));
}
});
var upload = multer({
storage: storage,
fileFilter: function(req, file, cb) {
if (/\.(png|jpg)$/i.test(file.originalname)) {
cb(null, true);
} else {
cb(null, false);
}
}
});
var fileUpload = upload.single('file');
router.post('/ajaxupload', function(req, res) {
fileUpload(req, res, function(err) {
if (err) {
res.json({
success: false,
message: 'upload failed'
});
return;
}
res.json({
success: true,
filename: req.file.path.replace(/public/, '')
});
});
});
return router;
};
my client side upload code:
var fd = new ForData();
fd.append('file', this.refs.myFile.files[0]); // use React refs
request
.post('/ajaxupload')
.send(fd)
.end(function(err, res) {
if (err) {
throw err;
}
// do something
});