I am trying to download the tar file using node js , file is saving but not able to open that file I have tried the following code
var fs = require("fs");
var fn = "version1.tgz";
var request = require('request');
var downloadUrl = "https://url/api/download?downloadFile="+fn+"&username=mkhun";
request({
url: downloadUrl,
method: 'POST',
}, function (err, resp, body) {
var rmv = body;
console.log(rmv);
fs.writeFile(fn,rmv,function(err,data){
console.log(err);
});
});
but the same thing is working with javascript ajax
var fn = "version1.tgz";
var xhttp = new XMLHttpRequest();
var downloadUrl = "https://url/api/download?downloadFile="+fn+"&username=mkhun";
console.log(downloadUrl);
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var blob = this.response;
var fileName = fn;
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=fileName;
link.click();
} else if(this.readyState == 2) {
xhttp.responseType = "blob";
}
};
xhttp.open("POST", downloadUrl , true);
xhttp.send();
I don't know how to fix the issue in node-red
This is an issue of encoding when receiving request data.
You can use streams to pipe the request into the filesystem directly from a Buffer. Otherwise, you can use encoding: null in the request options
request({
url: downloadUrl,
method: 'POST',
encoding: null
}, ...)
Related
I am creating a PDF and opening in a new browser. My issue is word 'blob:' is getting appended to the URL
blob:http://localhost:3000/a0b859c9-57a0-40b7-a60f-9d2a72ab3c14
and I would like to be 'http://localhost:3000/a0b859c9-57a0-40b7-a60f-9d2a72ab3c14'
Is there a way I could achieve this ? My code is below
const blob = new Blob([response.data], {type : 'application/pdf'});
var pdfFileUrl = URL.createObjectURL(blob);
window.open(pdfFileUrl);
URL.revokeObjectURL(pdfFileUrl);
update:
I tried below code as well. It also gives the same results.
''
const xhr = new XMLHttpRequest();
//Send the proper header information along with the request
// listen for `onload` event
xhr.onload = () => {
// process response
if (xhr.status == 200) {
// parse JSON data
// console.log( "Response Received")
// var pdfurl = URL.createObjectURL(xhr.response) ;
console.log(xhr.response)
window.open(URL.createObjectURL(xhr.response));
} else {
console.log(" In Error block")
console.error('Error!');
}
};
// create a `GET` request
xhr.open('POST', url);
xhr.responseType = 'blob'
xhr.setRequestHeader('Content-Type', 'application/json');
// send request
xhr.send(JSON.stringify(payload));''
My api call requires me to pass the api key in the headers, but I'm getting error back from the api service {"error":"2424452","message":"Invalid Api Key"}
I know my api key is valid as I can make the same api call in Python just fine, example:
req = requests.Session()
req.headers.update({'x-api-key': 'my-api-key', 'X-Product': 'my-product-name'})
req.get(url)
But in javscript, the same call errors out. I believe I'm not setting the headers correctly or something?
var req = new XMLHttpRequest();
req.onreadystatechange=handleStateChange;
req.open("GET", "url", true);
req.setRequestHeader("Host", "api.domain.com", "x-api-key", "my-api-key", "X-Product", "my-product-name");
req.send();
This XMLHttpRequest is not a browser call, rather in an application that support XMLHttpRequest.
setRequestHeader sets one header and takes two arguments (the name and the value).
If you want to set multiple headers, then call setRequestHeader multiple times. Don't add extra arguments to the first call.
In case you don't want to set multiple headers explicitly you can use
function setHeaders(headers){
for(let key in headers){
xhr.setRequestHeader(key, headers[key])
}
}
setHeaders({"Host":"api.domain.com","X-Requested-With":"XMLHttpRequest","contentType":"application/json"})
downloadReportFile(id, query): Observable<Object[]> {
var url = `${environment.baseUrl}report?report_name=${id}${query}`;
return Observable.create(observer => {
let xhr = new XMLHttpRequest();
xhr.open('GET', `${url}`, true);
xhr.setRequestHeader(environment.AUTH_TOKEN_HEADER_KEY, 'Bearer '+
localStorage.getItem(environment.AUTH_TOKEN_STORE_KEY));
xhr.responseType = 'blob';
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let filename = "Claim_Report.csv"
var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
var blob = new Blob([xhr.response], { type: "text/plain;charset=utf-8" });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
return;
}
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href = blobURL;
tempLink.setAttribute('download', filename);
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
setTimeout(() => {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(blobURL);
}, 100);
} else {
observer.error(xhr.response);
}
}
}
xhr.send();
});
}
I've got a microservice (in NancyFx) that works as expected for the following cURL command:
curl --verbose --form file=#"C:\test\image.png" http://localhost:8080/file/upload
The file shows up inside Nancy as expected at:
context.Request.Files[0] //The file bytes are here, yeah!!
Now I've got to get my web-client to send a selected file to the same service, in the same way.
TLDR; You can skip my failure examples below if you'd like
I've tried several versions of the following with no success:
var uploadForm = new FormData();
// Add the file to the request.
uploadForm.append("file", file, name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/file/upload', true);
xhr.onload = function() {
if (xhr.status === 200)
alert('File ' + name + 'Upload successfully!!!');
else errorFn("Upload Failure on file " + name);
};
//Send the data
xhr.send(uploadForm);
and several versions of the following, also with no success:
var postConfig = {
url: 'http://localhost:8080/file/upload',
data: uploadForm,
processData: false, //tries without this as well
type: "POST",
dataType: "application/x-www-form-urlencoded; charset=UTF-8",
cache: false,
success: successFn,
error: errorFn
}
$.ajax(postConfig);
I've tried the above with
file = direct reference to $('MyFileSelectorControl').files[0]
file being set with the following code:
var reader = new FileReader();
reader.onload = function (result) {
var fileContent = new Uint8Array(result.target.result);
var encContent = new SP.Base64EncodedByteArray();
for (var b = 0; b < fileContent.length; b++) {
encContent.append(fileContent[b]);
}
<Set file = encContent and send AJAZ as above>
};
reader.readAsArrayBuffer(fileInput);
Setting file = to fileContent above (IOW, after it has been through the reader, but not encoded.)
How do I submit this file from javascript (jQuery or standard) so that it works like it does from cURL?
Here is the code that finally worked. (Admittedly, I had thought I had already tried this and said so in my question)
var file = $('MyFileSelectorControl').files[0];
var uploadForm = new FormData();
// Add the file to the request.
uploadForm.append("file", file, name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/file/upload', true);
xhr.onload = function() {
if (xhr.status === 200)
alert('File ' + name + 'Upload successfully!!!');
else errorFn("Upload Failure on file " + name);
};
//Send the data
xhr.send(uploadForm);
I'm making an ajax call to an API that returns binary data. I'm wondering if its possible to take that binary data and display it for the client in a new window? This is what I'm doing right now. The problem is, the document opens up, but its completely blank.
$.ajax({
type: "POST",
url: apiURL,
data: xmlRequest,
complete: function(xhr, status) {
var bb = new window.WebKitBlobBuilder();
// Append the binary data to the blob
bb.append(xhr.responseText);
var blobURL = window.webkitURL.createObjectURL(bb.getBlob('application/pdf'));
window.open(blobURL);
}
});
Any ideas?
Okay, I figured it out. I had to specify the responseType as 'array buffer':
function downloadPDF() {
var xhr = new XMLHttpRequest();
xhr.open('POST', API_URL, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var bb = new window.WebKitBlobBuilder();
bb.append(this.response); // Note: not xhr.responseText
var blob = bb.getBlob('application/pdf');
var blobURL = window.webkitURL.createObjectURL(blob);
window.open(blobURL);
}
};
xhr.send(createRequest());
}
Tried to use the following code, but it doesn't work properly:
// download the file first
var req = new XMLHttpRequest();
req.open('GET', url, false);
req.overrideMimeType('text/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
// upload the file
req.open("POST", "http://mysite.com/upload", false);
req.setRequestHeader("Content-Length", req.responseText.length);
req.sendAsBinary(req.responseText); // What should I pass here?
if (req.status != 200) return '';
return req.responseText;
sendAsBinary is firefox function.
Upd. Also I've tried to upload that as part of the form:
var response = req.responseText;
var formData = new FormData();
formData.append("file", response);
req.open("POST", "http://mysite.com/upload", false);
req.send(formData);
But still not full data is received by the server.
Finally I've used the approach with temp file:
var downloadCompleted = false;
// download the file first
var persist = Components.classes["#mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Components.interfaces.nsIWebBrowserPersist);
// get OS temp folder
var file = Components.classes["#mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
file.append("temp.ext");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
var fURI = Services.io.newURI(url,null,null);
const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_FROM_CACHE;
persist.progressListener = {
onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {
},
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
downloadCompleted = true; // file has been downloaded
}
}
}
persist.saveURI(fURI, null, null, null, "", file);
var thread = Components.classes["#mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager)
.currentThread;
while (!downloadCompleted) // emulate synchronous request, not recommended approach
thread.processNextEvent(true);
// upload the file
var stream = Components.classes["#mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
stream.init(file, 0x04 | 0x08, 0644, 0x04); // file is an nsIFile instance
// try to determine the MIME type of the file
var mimeType = "text/plain";
try {
var mimeService = Components.classes["#mozilla.org/mime;1"]
.getService(Components.interfaces.nsIMIMEService);
mimeType = mimeService.getTypeFromFile(file); // file is an nsIFile instance
}
catch(e) { /* just use text/plain */ }
var req = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
req.open('POST', "http://mysite.com/upload", false);
req.setRequestHeader('Content-Type', mimeType);
req.send(stream);
// delete the file
file.remove(false);
You need to store the responseText in an intermediate variable before reusing the req object.
// download the file first
var req = new XMLHttpRequest();
req.open('GET', url, false);
req.overrideMimeType('text/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
var response = req.responseText;
// upload the file
req.open("POST", "http://mysite.com/upload", false);
req.setRequestHeader("Content-Length", response.length);
req.sendAsBinary(response);
if (req.status != 200) return '';
return req.responseText;
Update
Per the MDN page Using XMLHttpRequest, it looks like the above code won't work. Following is the proper way to get the binary response. In the end, you will have an array of unsigned integers which you could send back to the server and convert to binary. I think.
//req.responseType is only defined for FF6+
req.responseType = "arraybuffer";
req.send(null);
//req.response is for FF6+, req.mozResponseArrayBuffer is for FF < 6
var buffer = req.mozResponseArrayBuffer || req.response;
if (buffer) {
var byteArray = new Uint8Array(buffer);
}
Update 2
To submit the byteArray to a server, I would try something like the following untested, almost guaranteed not to work code.
req.open("POST", "http://mysite.com/upload", false);
req.setRequestHeader("Content-Length", byteArray.length);
//if this doesn't work, try byteArray.buffer
//if byteArray.buffer works, try skipping 'var byteArray = new Uint8Array(buffer);' altogether and just sending the buffer directly
req.send(byteArray);
Update 3
Could Using XMLHttpRequest from JavaScript modules / XPCOM components have anything to do with your issue?