How to access file uploaded by $http and HTML5 FileReader - javascript

I am trying to upload an image inside an Angular app, the code looks like this:
var f = document.getElementById('product-image').files[0],
r = new FileReader();
r.onloadend = function (e) {
var data = e.target.result;
$http({
method: 'POST',
data: data,
url: host + '/uploadFile?' + $rootScope.user._id,
headers: {
'Content-Type': 'multipart/form-data',
'X-File-Name': f.name,
'X-File-Size': f.size,
'X-File-Type': f.type
}
})
.success(function (data, status, headers, config) {
console.log(data)
});
}
r.readAsArrayBuffer(f);
When I have a look at Chrome Header fields of the request, they all look good with values.
Now, how do I access and save that file from the backend endpoint in NodeJS and Express? Do I look inside req variable as usual? Where do I look for the file and its content and meta?

basically, your post request is not 'multipart/form-data', and the data you sent to server is just binary array.
So you could just using NodeJS to save the trunk of binary data to some place.
You need to handle the data different way from normal form upload with files.
If you really want the server to handle the file upload as normal way, you could check the https://github.com/danialfarid/angular-file-upload

Related

Is it possible to read object from AJAX request on server side?

Actually, I'm trying to send video file in base64 but it the file is large (small files works fine) that's why ajax process not completed and I got 400 error.
So, I thought to send a file object like below so, I can read this object from the server-side. But I don't know if it is possible? OR is there any way through which I can handle large video file upload?
[object FileReader]
And here is my AJAX Code
var reader = new FileReader();
// this function is triggered once a call to readAsDataURL returns
reader.onload = async function(event){
var fileData = new FormData();
var fileType;
fileType = ".avi";
// console.log(my_script_vars.postID);
// fileData.append("file", event.target);
fileData.append("file", event.target.result);
fileData.append("action", "myaction");
fileData.append("filetype", fileType);
fileData.append("post_id", my_script_vars.postID);
jQuery.ajax({
url: 'https://www.reelme.app/sign-up/wp-admin/admin-ajax.php',
processData: false,
contentType: false,
cache: false,
data: fileData,
type: 'POST',
.......
.......
.......
});
}
Please help. Thanks in advance.
You shouldn't read the file into base64 and store everything in memory. screw that FileReader you have.
you are doing the right thing by using FormData, but a FormData can also append blob & files
// Simulate a file you would normally get from a file input or drag n drop
const file = new File(['abc'], 'sample.txt', { type: 'text/plain' })
const fd = new FormData()
fd.append('file', file)
then to upload it i would suggest that you use fetch instead of jQuery that requires all those processData & other config
const url = 'https://www.reelme.app/sign-up/wp-admin/admin-ajax.php'
fetch(url, { method: 'POST', body: fd })
.then(console.log, console.error)
JSON isn't meant to handle large binary data... b/c it's no good streaming format.

Best way of getting the HTTP Response with content-type 'application/octet-stream' in a variable?

I'm trying to get JSON data from a data provider with terrible, terrible documentation. Their API's response has a content-type of 'application/octet-stream' which, if I use my standard API consumption approach, ends-up serving me with a file containing the data... and setting Accept to 'application/json' in my Request does not make any difference.
So I'm trying to transform the octet-stream in JSON on my side and this is what I managed to do:
const request = require("request");
module.exports.test = function() {
var text = "";
var url = "XXX";
request
.get({
url: url,
headers: {
Accept: "application/json"
}
})
.on("response", function(response) {
response.on("data", function(data) {
text = text + data.toString();
});
})
.on("end", function() {
console.log(text); //This is where I stopped...
});
};
That's where I stopped, the JSON is printed in the log and so I could go on with my life and use the amazingly well named variable 'text' to do what I need to do with the data... BUT:
Is this the best way for dealing with octet-stream responses?
Should I trust a data provider (and pay for their data) that is not able to provide an API with responses other than application/octet-stream ?

Reactjs Nodejs file upload ftp via axios

I am trying to upload file using React Dropzone on ftp with Reactjs + AXIOS at front end, Nodejs + connect-multiparty at back end.
The problem is when I am sending file via front end using AXIOS, I am not getting the file at server in request.
My code to upload file using react-axios is
let data = new FormData()
data.append('file', file)
var setting = {
method: 'post',
url: 'my-server-url',
data:data,
headers: {
'Content-Type': 'multipart/form-data'
},
}
var response = axios(setting).then(response => { return response.data })
.catch(response => response = {
success: 500,
message: "Your submission could not be completed. Please Try Again!",
data: ""
});
while using postman, everything works fine. Server side api is working. only problem with client side request code.
Any help!!!
This is a very rookie mistake you're making probably because of the fact that you don't understand the way multipart works. For your client-side code to work, i.e form-data to be sent back to the backend, you need to:
Either remove the header and let the browser choose the header for you based on your data type
Or when using 'Content-Type': 'multipart/form-data', add a boundary to it
Multipart boundary looks like this,
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryABCDEFGHIJKLMNOPQRSTUVWXYZ'
Simply doing the following will solve the issue for you as the browser will take care of the headers needed.
axios.post('your-server-url', data).then(....)

Cloudinary Base64 Image uploading in angularjs

$http({method: 'POST',
url: $rootScope.CLOUDINARY_CONFIG.upload_url,
data : {
file : canvasImage,
resource_type : 'image',
format: "jpg",
timestamp : 1375363550,
api_key : $rootScope.CLOUDINARY_CONFIG.api_key,
signature : signature,
public_id : scope.model.public_id
},
headers : {"X-Requested-With": "XMLHttpRequest", "Content-Type" : "multipart/formData"}
}).success(function(data, status, headers, config) {
console.log("success");
}).error(function(data, status, headers, config) {
console.log("fail");
});
I am trying to upload a base64 image to cloudinary account. I have already checked whether the signature, api key, upload url and canvasImage are correct.
Yet whenever the request is sent,
I get an error in response :
{"error":{"message":"Missing required parameter - file"}}
On checking the request payload i can see the file parameter being passed.
The canvasImage is the base64 jpg. of the sort - data:image/jpeg;base64,/9j/4AAQSkZJRgABA.
Can't find anything of this sort in the cloudinary documentation.
Firstly, look into the FormData object. You'll want to use that if you're uploading multi-part form data.
Basically, the FormData object allows you to append files, blobs, and strings (if you attach something that isn't of those three, it will stringify it) using the only function that it has, append i.e:
var newForm = new FormData();
newForm.append('fileName', file);
newForm.append('api_key', $rootScope.CLOUDINARY_CONFIG.api_key);
newForm.append('signature', signature);
newForm.append(public_id, scope.model.public_id);
and so on..
Next.
Set your content-type to undefined instead of multi-part form data. This seems unintuitive, however, what happens is that the browser will automatically set the proper boundary for you and will automatically set the content-type back to multipart/formdata.
Additionally, add a transformRequest to the config set to angular.identity. The browser will try to serialize your form data, therefore you need to stop it from doing so by setting transformRequest to angular.identity.
The overall $http request should look something like this:
$http.post(url, newForm, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data){
// success
})
.error(function(err){
// log error
})
Also note that FormData is tricky to deal with you because if you console your FormData object, i.e.(console.log(newForm)) all it will show is: FormData {append: function}

Form submit File and complex Json

How do I submit complex Json object along with a file upload?
I can do a simple json object successfully, only fails with a complex json:
e.g. [file] + { simple: object } -- okay
e.g. [file] + {some: {complex: 'asdf'}, object:['str1','str2']} -- fails
//here is the simple json data
var params = {simple: 'jsonData'};
//here is the header to enable json stuff
var headers = {
'Content-Type': 'application/json',
'Accept': 'application/json, text/javascript, */*',
'dataType': 'json'
};
//assume we have some files in that html form
var files = fi.button.fileInputEl.dom.files;
form.submit({
url: '/some/api',
waitMsg: 'Uploading your file...',
headers: headers,
params: params,
success: function(a, b) {
//done...
}
});
The code above fails when params is a complex Json object with more than one layer. I am using ExtJs, for those who uses JQuery I guess it is html form so my question would be the same across different js libs.
When doing file uploading, Ext does a form post to a hidden iframe, so you need to parse the data as such.

Categories

Resources