Upload Base64 Video to Parse.com - Javascript - javascript

I'm trying to get my base64 video data to save to Parse.com. I'm using the same technique for images and it works fine, but video will not save for some reason. I've have been trying to debug this issue for weeks with no success. I basically copied the technique/code after I had images working this way... using base64 I figured it would be more or less work the same...
My video data looks like this:
data:video/3gpp;base64,AAAAGGZ0eXAzZ3A0AAAAAGlzb2.....
The video being saved is only ~56kb - ~1mb. Saving to Parse.com which has a 10mb file limit. I've checked my data and everything seems right, right up until I try to save the file to Parse.com, which spits back an error 400.
POST https://api.parse.com/1/files/myVideo.3gp 400 (Bad Request)
along with this in my XHR Response :
{"code":107,"error":"base64 field cannot be decoded"}
Anyone have any insight as to why it may not be working:
var videoFile = new Parse.File('myVideo.3gp', {
base64: _params.videoData
});
// save the parse file
videoFile
.save({
success: function(resp) {
window.ERROR = "Success: " + resp;
},
error: function(e, r) {
window.ERROR = "Error: " + e + " : " + r;
}
})
.then(function() {
_params.videoData = null;
// create object to hold caption and file reference
var videoObject = new ImageObject();
// set object properties
videoObject.set('title', _params.title);
videoObject.set('user', Parse.User.current());
videoObject.set('img', videoFile);
if (_params.location !== undefined) {
videoObject.set('location', new Parse.GeoPoint(_params.location.latitude, _params.location.longitude));
}
// save object to parse backend
videoObject
.save()
.then(function(resp) {
console.log('Posted Video', resp);
// Add User QtdPhoto
defer.resolve(resp);
});
}, function(error) {
console.log('Error', error);
defer.reject(error);
});

HTTP Status code 400 means that your request is not formed correctly. Can you copy-paste the actual HTTP request that is being made from DevTools or Firebug.
On the other note, if the request is being cut off after exactly the same amount of length. It may be caused by a firewall/router on your side of the equation. Are you behind a corporate network?
UPDATE:
As a response to author's comment. There are 2 ways to save file to Parse.com:
Using REST API
Using simple HTTP POST request
First method
I prefer using HTML5 file field to handle the file for me. It allows users to choose a file.
var videoFile = document.getElementById("your-file");
if (videoFile.files.length > 0) {
var parseFile = new Parse.File("myVideo.3gp", videoFile.files[0]);
}
parseFile.save().then(function() {
// Success
}, function(error) {
// Error: alert() or log()
console.log(error);
});
<input id="your-file" type="file" />
Second method:
Make a POST request like so or read the docs here.
curl -X POST \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: video/3gp" \
--data-binary '#your-local-file.3gp' \
https://api.parse.com/1/files/videoFile.3gp
Just do the equivalent of this curl in your AJAX request. Is coding in native environment an option? Or, are you coding for PhoneGap, Ionic, etc.?

Related

HTTP Content-Length header calculation in javascript

I am new in javascript and node-js. I have an issue in calling a rest endpoint. My problem is when I try to call the endpoint using Postman everything is ok. I can see the calculated Content-Length header in Postman console. But when I try to call the same endpoint in javascript something is wrong because the calculated Content-Length is a bit lower than the calculated one by Postman. Here is my node.js code that I am using to call the endpoint. Note that the API is multipart API that is used for uploading the files.
file = fs.readFileSync('/Users/.../Documents/doc.pdf')
form = new FormData()
form.append('file', file)
headers = Object.assign({'Content-Length': form.getLengthSync() }, form.getHeaders())
config = {
method: 'post',
url: 'https://staging:...',
headers: headers,
data : form
};
axios(config).then((res) ->
console.log("The file is posted successfully. status is : " + res.status)
).catch((err) ->
console.log("The error occurred in posting file : " + err)
)
Can you please tell me what is missing here? for example for a specific file that I am testing the postman calculated value is 388 but the code calculated it as 379 for the same file.
Note: when I hardcode the value with the value from Postman everything is ok.
Issue #426 in the form-data repository seems to describe a solution for your problem.
I gave it a try locally and managed to get the desired results by applying what described in the issue:
const filePath = '/Users/.../Documents/doc.pdf';
const form = new FormData();
let options = {
knownLength: fs.statSync(filePath).size
}
form.append(
'file',
fs.createReadStream(filePath),
options,
);
I gather the issue is related to the acclaration made in the getLengthSync specification, which states that stream lengths' aren't calculated, hence the extra step that must be taken in order to provide the correct file length to the FormData instance.

My restify POST error data isn't visible in the client JavaScript

I'm trying to implement a POST REST call in node.js using restify. In this instance, I want to send an error to the browser. Unfortunately, I haven't figured out how to send the error data so that the browser JavaScript can see the error data I sent.
When I call the doPost() function on the browser, it performs an ajax POST call to my server. The server code returns with an error 400 and a small JSON object containing an error message.
The browser then goes to the .fail() function. However, the textStatus is "error", errorThrown is an empty string, and the jqXHR properties are readyState : 0, responseText : "", status : 0, statusText : "error".
What can I do to get my error data from Node to the client browser?
Here is the jQuery code that runs in the browser:
function doPost() {
$.ajax({
url: "http://localhost:3979/api/address",
type: "POST",
// Request body.
data: {key: "mykey", address: "myaddress"}
})
.done(function(data) {
// Show the formatted JSON in the text area.
$("#outputTextArea").val(JSON.stringify(data, null, 2));
})
.fail(function(jqXHR, textStatus, errorThrown) {
// An error occurred. Display the error information.
$("#outputTextArea").val(
"status: " + jqXHR.status +
", textStatus: " + textStatus +
", errorThrown" + errorThrown + "\r\n");
});
}
And here is the Node.js code that runs on the server:
const restify = require('restify');
// Create the server.
let server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3979, function () {
console.log(`${server.name} listening to ${server.url}`);
});
// POST call that returns an error.
server.post("/api/address", async (req, res) => {
res.send(400, {errorMessage: "The value given does not appear to be valid."});
});
Edit: Both res.status(422); res.send("The value given does not appear to be valid."); and res.send(new BadRequestError('meh')); fail in the exact same way. The jqXHR properties are the same (zero for readyState and status, empty string for responseText), textStatus is "error, and errorThrown is an empty string.
I tested my .ajax code against a known working POST call, and it gets proper values, including a JSON responseText.
Can someone please try this out in node.js and show me what I'm doing wrong, or show me the right way to send an error to the browser. So far, nothing works.
Edit: After further tests and experiments, this time with curl, I found that my POST call works and returns expected values.
I used this curl command to retrieve the status code:
curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:3979/api/address
And received this response: 400
I then used this curl command:
curl -X POST http://localhost:3979/api/address
And received this response:
{"errorMessage":"The value given does not appear to be valid."}
So it appears that the problem exists on the browser end.
This stackoverflow question seems to indicate a cross domain problem (page: www.mydomain.com/register, REST: server.mydomain.com/rest). However, I am doing all of this using localhost, so I don't see how the browser could see a cross domain issue here.
Any ideas on how to get REST POST errors to show up in the browser when running on localhost?

Native JS fetch API complete error handling. How?

I've put together the following code from learning about the fetch API. I am trying to replace AJAX and this looks wonderful so far.
Main Question:
According to the Fetch API documentation...
A fetch() promise will reject with a TypeError when a network error is
encountered or CORS is misconfigured on the server side, although this
usually means permission issues or similar — a 404 does not constitute
a network error, for example.
Having the 3 technologies working together...
If I disable the Web Server I get:
NetworkError when attempting to fetch resource.
Wonderful. That works great.
If I disable MySQL I get my custom error from PHP:
MySQL server down?
Wonderful. That works great.
If I disable PHP I get exactly nothing because the only way I can think of to pass through the Web Server request and trigger an error at the PHP level is with a... timeout.
After some research, I don't think there is a timeout option... at least not yet.
How could I implement it in the code below?
// CLICK EVENT
$( "#btn_test" ).on('click', function() {
// Call function
test1();
});
function test1() {
// json() - Returns a promise that resolves with a JSON object.
function json_response(response) {
// Check if response was ok.
if(response.ok) {
return response.json()
}
}
// data - Access JSON data & process it.
function json_response_data(data) {
console.log('json_response_data: ', data);
}
// URL to post request to...
var url = 'data_get_json_select_distinct_client.php';
// Sample serializeArray() from html form data.
// <input type="text" name="CLIENT_ID" value="1000">
var post_data = [{
"name":"CLIENT_ID",
"value":"1000"
}];
// STRINGIFY
post_data = JSON.stringify(post_data);
// FETCH
fetch(url, {
method: 'post',
headers: new Headers({'Content-Type': 'application/json; charset=utf-8'}),
body: post_data
})
// VALID JSON FROM SERVER?
.then(json_response)
// ACCESS JSON DATA.
.then(json_response_data)
// ERROR.
.catch(function(error) {
console.log('Web server down?: ', error.message);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<button type="button" id="btn_test">FETCH RECORD</button>
Your server should be returning some sort of 5xx error code, should there be a problem server-side. This error is catchable in your JS.

Angular HTTP GET request returns undefined while working in browser

I'am learning AngularJs and I've tried to write a very basic script sending an http request to Ebay public API, I've signed up and got my API keys, I've read the docs several times and wrote this basic code :
$scope.getQueryUrl = function () {
// Some unrelated code ...
$scope.queryUrl["Ebay"] = "http://svcs.sandbox.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsByKeywords&SERVICE-NAME=FindingService&SERVICE-VERSION=1.0.0&GLOBAL-ID=EBAY-US&SECURITY-APPNAME="+dataAuth.EbayKeyApi+"&RESPONSE-DATA-FORMAT=XML&keywords="+$scope.qtext ;
};
$scope.sendRequest = function () {
$scope.getQueryUrl(); // Gets the query url after adding all the parameters
alert($scope.queryUrl.Ebay);
$http.get($scope.queryUrl["Ebay"]).then(
function(response){
alert("success" + response.data );
},
function(response){
alert("error" + response.statusCode );
});
};
How this code should work :
It should create a formated Ebay query url, send it through HTTP GET request and sending back the response .
Note : $scope.qtext & dataAuth.EbayKeyApi are already assigned with their respective values .
What's the problem:
The problem is that using this Angularjs script, the code doesn't work, the alert "Error" is shown, and the response.statusCode is undefined .
But when I copy the formatted Ebay query link in Firefox it works perfectly and the XML response is shown .
The formatted Ebay query was generated using the script provided .
I think it's a header related problem .
$http has some default headers defined. $http sends Json payload and accepts Json as the response by default. Since you are dealing with XML you have to explicitly specify the accepted response type as XML using the header:
Accept: application/xml
Please use the following function with appropriate headers and you should get the response. Also, please look into any Cross Origin Resource Sharing (CORS) restrictions on the ebay API.
function getRequest(url) {
$http({
method: "GET",
url: url,
headers: {
'Content-Type': 'application/xml, text/xml',
'Accept': 'application/xml, text/plain, * / *'
}
})
.then(function (response) {
alert(response.data);
},
function (error) {
alert (error);
});
}
Thank you,
Soma.

Reddit submit API 500 error

I'm attempting to use the reddit API to make posts, but the server is returning 500 errors.
For example, I tried posting to this URL with my cookie set:
http://www.reddit.com/api/submit?title=testtitle&sr=compsci&uh=<modhash_goes_here>&text=testtext&kind=self
And my Chrome Dev Tools prints the following error:
POST <my long URL goes here> 500 (Internal Server Error)
I read somewhere on StackOverflow that you need both the modhash and the cookie, so that's what I'm using. I tried without the modhash, and I tried with the superfluous "r=subreddit" parameter listed on Apigee. Neither helped.
Why would I be getting a 500 error?
You're not supposed to POST data in the URL; you set the data in the POST object, and the POST that.... Which makes sense, because you POST things like passwords. For example (using jQuery):
$.post('http://www.reddit.com/api/vote',
{
'id' : 't3_' + id,
'dir': dir,
'uh' : mod_hash
},
function(data) {
var err = false;
for (var i in data) {
if (data.hasOwnProperty(i)) {
err = true;
break;
}
}
// No error!
callback(err);
});
URLs just happen to work for some reddit API calls because they implemented them on GET in addition to POST.

Categories

Resources