I need a way to insert the text downloaded from a .txt file from a URL into an element or variable which i can use further.
I have tried adding the URL to an object element which displays the text correctly, but I do not know how to add this text into a variable.
var storage = firebase.storage();
var storageRef = storage.ref();
var tangRef = storageRef.child('Recs');
var fileRef = tangRef.child("rec3.txt");
fileRef.getDownloadURL().then(function(url)
{
alert(url);
var para = document.getElementById('p1');
var par = document.createElement("object");
par.setAttribute('data', url);
para.appendChild(par);
}).catch(function(error)
{
console.error(error);
});
As mentionned, you can get some file through an object HTML element as you can do through a script HTML element to load a file. From these elements you won't have a same-origin policy problem, that's why your document is loaded with setAttribute and appendChild.
If you tried to access a resource by XHR or if you tried to interact with a document (both by JS), which are not from the same origin than your current resource, you will need to manage a same-origin policy mechanism see : https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
You can choose XHR or choose to access the nested document from the object HTML element, in both case you will have the same-origin policy problem. This is for security reasons which are linked with JavaScript.
If you choose nested document you could do something like this :
<div id="p1"></div>
<script>
var url = "https://firebasestorage.googleapis.com/v0/b/ninjatest-1b0ab.appspot.com/o/random%20text%20file.txt?alt=media&token=c09ae3ee-6a01-4f2b-b2b3-2f57ed7ff111";
// or
// var url = "http://localhost:4000/file.txt";
var para = document.getElementById('p1');
var par = document.createElement("object");
par.setAttribute('data', url);
para.appendChild(par);
par.onload = function() {
var doc = par.contentDocument || par.contentWindow.document;
var data = doc.body.childNodes[0].innerHTML;
console.log(data);
};
</script>
If you run this code, you can see that it doesn't accept cross-origin. This is because i'm trying to get a document (nested in the HTML document) which is from another domain. The browser won't let me access it. In the other hand, if i run in local with a node server, it allows me to get it without the error.
If you choose to use XHR (XMLHttpRequest) you can do something like that :
var data;
var url = "https://firebasestorage.googleapis.com/v0/b/ninjatest-1b0ab.appspot.com/o/random%20text%20file.txt?alt=media&token=c09ae3ee-6a01-4f2b-b2b3-2f57ed7ff111";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
data = xhr.responseText;
console.log(data);
}
};
xhr.open('GET', url);
xhr.send();
Again here, it won't work because of the different origin. In the two situations, it's the browser which implements a security rule. You can fix it if you have access to the server part. On the server, you could tell the browser (by HTTP header) to allows client from different origin.
With XHR you need to search about CORS.
With Nested document, you can look here :
SecurityError: Blocked a frame with origin from accessing a cross-origin frame
How Can I Bypass the X-Frame-Options: SAMEORIGIN HTTP Header?
If you don't have access to the server part, you could grab the file with a GET request from a server that you own (and so have access to the server part). In this case, you won't have the browser security issue because from your server, you will serve the file without the restriction of same-origin. It will be a proxy server solution.
With Firebase
When you create project with Firebase you can configurate the server part to allow the XHR as mention here : https://firebase.google.com/docs/storage/web/download-files#download_data_via_url
Firstly install Google Cloud SDK to have gsutil : https://cloud.google.com/storage/docs/gsutil_install#install
Then create a .json file on your computer : https://cloud.google.com/storage/docs/configuring-cors#configure-cors-bucket
Then execute this command : gsutil cors set cors.json gs://<your-cloud-storage-bucket>
JSON file example :
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
I created a Firebase account, tried it and it works very well.
Working example with XHR (you can run it) :
var data;
var url = "https://firebasestorage.googleapis.com/v0/b/first-app-a7872.appspot.com/o/firebase.txt?alt=media&token=925fef9e-750e-40e5-aa92-bdfe8204d32e";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
data = xhr.responseText;
console.log(data);
}
};
xhr.open('GET', url);
xhr.send();
https://codepen.io/anon/pen/JmoqQY?editors=1010
In HTML file:
<div id="p1">
</div>
script
url = "https://firebasestorage.googleapis.com/v0/b/ninjatest-1b0ab.appspot.com/o/random%20text%20file.txt?alt=media&token=c09ae3ee-6a01-4f2b-b2b3-2f57ed7ff111"
var para = document.getElementById('p1');
var par = document.createElement("object");
par.setAttribute('data', url);
para.appendChild(par);
EDIT: I made a stackblitz to try to see if I could extract the data in the text file into a variable for manipulation.
https://stackblitz.com/edit/angular-eyhaj5
I was unable to find a way. Problem is that because of CORS policy in browsers you are not supposed to open files outside of your own site.
To get around this you have to either have to send the URL to a function on your server that downloads the textFile and then makes it accessible in a folder.
Or you could set up a proxy server that allows cors. Or you could ask the owner of the text file to make it into an API.
Possibly it was a bad idea to put the textfile in firestorage in the first place. If you are the owner of the text file, it would maybe be better to put the text in a firestore database rather than save it as a textfile.
Related
I have an old Chrome extension that added drag-and-drop functionality to a site with file uploads. The site has pages on one subdomain (ex: https://foo.site.com/page1.php, https://foo.site.com/page2.php..), and the upload endpoint is on another subdomain (ex: https://bar.site.com/upload.php). Starting in some previous Chrome version, the extension stopped working because of stricter CORS rules. The POST to upload the file seems to succeed, but the response is blocked with a CORB error, and I need the response to know where the file's new remote path is.
I've attempted to refactor by moving requests from the content script to the background script, per Google's guidelines. However, I can't figure out how to share a file drag-and-dropped onto the page with the background script. Here's some sample code:
content.js:
var setupDragAndDrop = function () {
(
document.getElementById("some_element")
).addEventListener("drop", function (e) {
for (var t = 0, s = e.dataTransfer.files.length; t < s; t++)
upload(e.dataTransfer.files[t], function (e) {
insertResponseOnPage(e); // Use the upload response to show the new remote path on the page
});
e.preventDefault();
});
},
var upload = function(file, callback) {
chrome.runtime.sendMessage(
{
need: "upload",
file: file,
callback: callback
}
);
}
background.js (there is some other logic that lets the message end up at this method, but it does end up here with the file and callback):
var upload = function(file, callback) {
var formData = new FormData();
formData.append('file', file);
const UPLOAD_URL = 'https://bar.site.com/upload.php';
var xhr = new XMLHttpRequest();
xhr.open('POST', UPLOAD_URL, true);
xhr.withCredentials = "true";
xhr.onload = callback;
xhr.send(formData);
};
This issue I'm seeing is that the file ending up on the background page is an empty object. I believe I read somewhere that whatever is sent with the message API needs to be JSON serializable, so I'm assuming File is not? I get the same behavior if I attempt to send a FormData object as well. I've also tried going down the route of somehow getting the file path instead and recreating the file in the background page, but apparently you can't get the path from a system file in JS for security reasons.
Is there any way to fix up this extension? I do not own the site this extension attempts to add functionality to, so I can't move the upload endpoint onto the same subdomain.
I'm loading a motion jpeg from third-party site, which I can trust. I'm trying to getImageData() but the browser (Chrome 23.0) complains that:
Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.
There are some similar questions on SO, but they are using local file and I'm using third party media. My script runs on a shared server and I don't own the remote server.
I tried img.crossOrigin = 'Anonymous' or img.crossOrigin = '' (see this post on the Chromium blog about CORS), but it didn't help. Any idea on how can I getImageData on a canvas with cross-origin data? Thanks!
You cannot reset the crossOrigin flag once it is tainted, but if you know before hand what the image is you can convert it to a data url, see Drawing an image from a data URL to a canvas
But no, you cannot and should not be using getImageData() from external sources that don't support CORS
While the question is very old the problem remains and there is little on the web to solve it. I came up with a solution I want to share:
You can use the image (or video) without the crossorigin attribute set first and test if you can get a HEAD request thru to the same resource via AJAX. If that fails, you cannot use the resource. if it succeeds you can add the attribute and re-set the source of the image/video with a timestamp attached which reloads it.
This workaround allows you to show your resource to the user and simply hide some functions if CORS is not supported.
HTML:
<img id="testImage" src="path/to/image.png?_t=1234">
JavaScript:
var target = $("#testImage")[0];
currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
url: currentSrcUrl,
type:'HEAD',
withCredentials: true
})
.done(function() {
// things worked out, we can add the CORS attribute and reset the source
target.crossOrigin = "anonymous";
target.src = currentSrcUrl;
console.warn("Download enabled - CORS Headers present or not required");
/* show make-image-out-of-canvas-functions here */
})
.fail(function() {
console.warn("Download disabled - CORS Headers missing");
/* ... or hide make-image-out-of-canvas-functions here */
});
Tested and working in IE10+11 and current Chrome 31, FF25, Safari 6 (Desktop).
In IE10 and FF you might encounter a problem if and only if you try to access http-files from a https-script. I don't know about a workaround for that yet.
UPDATE Jan 2014:
The required CORS headers for this should be as follows (Apache config syntax):
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"
the x-header is required for the ajax request only. It's not used by all but by most browsers as far as I can tell
Also worth noting that the CORS will apply if you are working locally regardless of if the resource is in the same directory as the index.html file you are working with. For me this mean the CORS problems disappeared when I uploaded it to my server, since that has a domain.
You can use base64 of the image on canvas,
While converting into base64 you can use a proxy URL (https://cors-anywhere.herokuapp.com/) before your image path to avoid cross-origin issue
check full details here
https://stackoverflow.com/a/44199382/5172571
var getDataUri = function (targetUrl, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
xhr.open('GET', proxyUrl + targetUrl);
xhr.responseType = 'blob';
xhr.send();
};
getDataUri(path, function (base64) {
// base64 availlable here
})
I am doing a chrome extension capable of getting from a webpage an image, and after I got it, I'm trying to upload it to an intranet server automatically without user iteration.
I am doing this right now.
This is on Content_script.js
...
x = $(frame1).contents().find("#image");
chrome.extension.sendRequest(x[0].src);
...
This is on background.js
chrome.extension.onRequest.addListener(function(links) {
chrome.downloads.download( { url: links ,
conflictAction: "overwrite",
filename: "get_image.jpg" },
function(DescargaId) {
var formData = new FormData();
formData.append("doc", Blob, "~/Downloads/get_image.jpg");
var request = new XMLHttpRequest();
request.open("POST", "http://192.168.0.30/app_get_pictures/upload_img.php");
request.setRequestHeader("Content-Type", "multipart/form-data");
request.send(formData);
} );
This on upload_img.php
...
$uploaddir = $_SERVER['DOCUMENT_ROOT'].'/app_get_pictures/images/';
$uploadfile = $uploaddir . basename($_FILES['doc']['name']);
move_uploaded_file($_FILES['doc']['tmp_name'], $uploadfile);
...
With this, I already download the image successfully to the local machine, but can't upload the image to the server.
It is possible to do this, or even if I can upload the image to the server directly without download it first to the local machine.
Note: I don't have any tag form on a popup page in the extension solution, and I don't have a popup page neither, because as I already said, I don't need any iteration from the user.
Thanks for your help!
Thanks to https://stackoverflow.com/users/934239/xan I resolved this problem using his advise, here is the resulting working code.
...
// With this I can download or get content image into var blob
var xhr = new XMLHttpRequest();
var kima = $(frame1).contents().find("#image");
xhr.open('GET',kima[0].src,true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = new Blob([this.response], {type: 'image/png'});
send_image(blob);
}
};
xhr.send();
....
// After the image is loaded into var blob, it can be send
// to the server side
function send_image(x){
var formData = new FormData();
formData.append("doc", x);
var request = new XMLHttpRequest();
request.open("POST", "http://192.168.0.30/app_get_image/upload_img.php");
request.send(formData);
}
All this code into the content_script of the chrome extension. Also the code of the background using API download isn't needed anymore.
Hope this could works for anybody else.
Thanks again.
Besides the fact that the callback of downloads.download does NOT indicate that the file is already downloaded (only that the download is queued)..
formData.append("doc", Blob, "~/Downloads/get_image.jpg");
What do you think this code does? Documentation, for reference.
The second parameter is supposed to hold the data of the file; the third parameter is just the file name for the purposes of naming anonymous data (e.g. in a Blob)
Instead, you pass the Blob object itself; not an instance of Blob with the data.
In fact, with this architecture, you won't be able to upload the file, since at no point does chrome.downloads API give you access to the file's contents, and you can't just access a file on a disk by filename (which is what I think you thought this code would do).
To actually access the data, you need to request it yourself with XHR (or Fetch API if you want to be "modern"). Then, you get the response object which you can request to be a Blob. Then, you can both upload the blob and invoke chrome.downloads together with createObjectURL to "download" it from your extension's memory.
I'm loading a motion jpeg from third-party site, which I can trust. I'm trying to getImageData() but the browser (Chrome 23.0) complains that:
Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.
There are some similar questions on SO, but they are using local file and I'm using third party media. My script runs on a shared server and I don't own the remote server.
I tried img.crossOrigin = 'Anonymous' or img.crossOrigin = '' (see this post on the Chromium blog about CORS), but it didn't help. Any idea on how can I getImageData on a canvas with cross-origin data? Thanks!
You cannot reset the crossOrigin flag once it is tainted, but if you know before hand what the image is you can convert it to a data url, see Drawing an image from a data URL to a canvas
But no, you cannot and should not be using getImageData() from external sources that don't support CORS
While the question is very old the problem remains and there is little on the web to solve it. I came up with a solution I want to share:
You can use the image (or video) without the crossorigin attribute set first and test if you can get a HEAD request thru to the same resource via AJAX. If that fails, you cannot use the resource. if it succeeds you can add the attribute and re-set the source of the image/video with a timestamp attached which reloads it.
This workaround allows you to show your resource to the user and simply hide some functions if CORS is not supported.
HTML:
<img id="testImage" src="path/to/image.png?_t=1234">
JavaScript:
var target = $("#testImage")[0];
currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
url: currentSrcUrl,
type:'HEAD',
withCredentials: true
})
.done(function() {
// things worked out, we can add the CORS attribute and reset the source
target.crossOrigin = "anonymous";
target.src = currentSrcUrl;
console.warn("Download enabled - CORS Headers present or not required");
/* show make-image-out-of-canvas-functions here */
})
.fail(function() {
console.warn("Download disabled - CORS Headers missing");
/* ... or hide make-image-out-of-canvas-functions here */
});
Tested and working in IE10+11 and current Chrome 31, FF25, Safari 6 (Desktop).
In IE10 and FF you might encounter a problem if and only if you try to access http-files from a https-script. I don't know about a workaround for that yet.
UPDATE Jan 2014:
The required CORS headers for this should be as follows (Apache config syntax):
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"
the x-header is required for the ajax request only. It's not used by all but by most browsers as far as I can tell
Also worth noting that the CORS will apply if you are working locally regardless of if the resource is in the same directory as the index.html file you are working with. For me this mean the CORS problems disappeared when I uploaded it to my server, since that has a domain.
You can use base64 of the image on canvas,
While converting into base64 you can use a proxy URL (https://cors-anywhere.herokuapp.com/) before your image path to avoid cross-origin issue
check full details here
https://stackoverflow.com/a/44199382/5172571
var getDataUri = function (targetUrl, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
xhr.open('GET', proxyUrl + targetUrl);
xhr.responseType = 'blob';
xhr.send();
};
getDataUri(path, function (base64) {
// base64 availlable here
})
I am trying to parse some json on an external site but I am having trouble. It must be with JavaScript or JQuery, as it is for a chrome extension. To get to the point:
I need to get the number from an external URL with the json {"_visitor_alertsUnread":"0"} and set the number returned to a variable. How do I go about doing this?
I have tried several things such as JSON.parse but it isn't working:(
In short: How do I get the number from this json, which is on an external site, and set it to a variable?
You cannot get data from an external URL (in a different domain) in Javascript unless the site supports JSONP or Cross-Origin Resource Sharing. If it does, then use XMLHttpRequest to get the data and JSON.parse() to read it.
Script:
var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'example.com/json', true );
xhr.onload = function () {
var unread = window.JSON.parse( xhr.responseText )._visitor_alertsUnread;
};
xhr.onerror = function () {
//process error
};
xhr.send();
Try this with http://api.jquery.com/jQuery.getJSON/
$.getJSON('your_url', function (jsonobj) {
var unread;
unread = jsonobj._visitor_alertsUnread;
});