Download Google Drive file from url and send with post to backend - javascript

I am trying to download a file from an url (chrome drive file) in javascript; and want to send it to my backend (php - laravel).
var url = file.downloadUrl !== undefined ? file.webContentLink : file.exportLinks['application/pdf'];
console.log(url) // if I go to url, it downloads the file
if (url !== undefined) {
var remote = new XMLHttpRequest();
remote.open('GET', url);
remote.setRequestHeader('Authorization', 'Bearer ' + gapi.client.getToken().access_token);
remote.setRequestHeader('Access-Control-Allow-Origin', '*');
remote.onload = function(e) {
vm.handle_download(remote.responseText, file, 200); // do something with the fetched content;
};
remote.onerror = function(e) {
vm.handle_download('error response', null, remote.statusText);
};
remote.send();
} else vm.handle_download('no downloadable url', {
file: null,
status: 'error'
});
and on handle
handle_download: function (content, file, status) {
if (status !== 200) {
console.log('error occured on status')
return;
}
}
Failed to load https://drive.google.com/uc?id=1D12321ofd4CNG-m9_Mp4aiDcnibNf&export=download: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://test.dev' is therefore not allowed access.

This is an intended behavior due to same origin policy in the web. Since you're doing this for testing purposes, try this Allow-Control-Allow-Origin chrome extension.
You can read more about how to implement this in Using CORS tutorial.
This SO post may also offer additional insight.

Related

GoogleDrive API (javascript): no file download because of CORS

With this code, before an year about i could get the file via XMLHttpsRequest.
Now this do not more work, because of the error:
Access to XMLHttpRequest at 'https://drive.google.com/uc?id=1zGxNBh-YTAXu74v855l2b_LPmLUaomqZ&export=download' from origin 'https://encrypt.pdfzorro.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Is there a way at now, to get the file via javascript. I can not use any server solution, the file should go direct from googleDrive to the browser from the user.. without go on a server (with php e.g.) first.
function downloadFileContent(fileId){
gapi.client.request({
'path': '/drive/v2/files/' + fileId,
'method': 'GET',
callback: function ( theResponseJS, theResponseTXT ) {
var myToken = gapi.auth.getToken();
var myXHR = new XMLHttpRequest();
myXHR.open('GET', theResponseJS.downloadUrl, true );
myXHR.responseType = 'arraybuffer';
myXHR.setRequestHeader('Authorization', 'Bearer ' + myToken.access_token );
myXHR.onreadystatechange = function( theProgressEvent ) {
if (myXHR.readyState == 4) {
// 1=connection ok, 2=Request received, 3=running, 4=terminated
if ( myXHR.status == 200 ) {
// 200=OK
cossole.log(myXHR.response);
}
}
}
myXHR.send();
}
});
}

Failed cross domain xml Get Request

Im trying to help a friend out with a program but my coding experience is somewhat dated (10 years give or take). Where trying to pull data from a database via their API. Im making this request via a XMLhttpRequest but im having issues even getting to the Server.
The error that occurs:
Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost/jasper/api.shiftbase.com/api/rosters?min_date=2020-07-13&max_date=2020-12-31&department_id=24477
Its trying to search for the url on my own domain. But I need it to search cross domain.
The entire function:
function getRequest(){
var _request = new XMLHttpRequest();
var key = myKeyHere;
var url = "api.shiftbase.com/api/rosters?min_date=2020-07-13&max_date=2020-12-31&department_id=24477";
_request.onreadystatechange = function(event){
console.log(_request.readyState + " + " + _request.status);
if (_request.readyState == 4){
if ((_request.status >= 200 && _request.status < 300) || _request.status == 304){
alert(_request.responseText);
} else {
alert('Request was unsucceful: ' + _request.status);
}
}
};
_request.open("get", url, true);
_request.setRequestHeader("Accept", "application/JSON", false);
_request.setRequestHeader("Content-Type", "application/JSON", false);
_request.setRequestHeader("Authorization", key, false);
_request.send(null);
};
I've also read a lot about CORS and how this affects these kinds of requests cross domain, but i don't quite understand how it works and how i can work arround it.
Any help is appreciated.
First of all you need to prefix your URL with https://. This way you make a request to the external server instead of localhost. The second thing is that in your headers the application/JSON should be application/json.
Also dont forget that your key needs to be prefixed with "API". Example API [some_random_key]
I've tested the following code and it worked. You just have to add your own API KEY.
function getRequest(){
var _request = new XMLHttpRequest();
var key = "API [replace_this_with_your_key]"; // Example: "API a1b2c3d4e5f6g7h8i9"
var url = "https://api.shiftbase.com/api/rosters?min_date=2020-07-13&max_date=2020-12-31&department_id=24477";
_request.onreadystatechange = function(event){
console.log(_request.readyState + " + " + _request.status);
if (_request.readyState == 4){
if ((_request.status >= 200 && _request.status < 300) || _request.status == 304){
alert(_request.responseText);
} else {
alert('Request was unsucceful: ' + _request.status);
}
}
};
_request.open("get", url, true);
_request.setRequestHeader("Accept", "application/json", false);
_request.setRequestHeader("Content-Type", "application/json", false);
_request.setRequestHeader("Authorization", key, false);
_request.send(null);
};
Try to add // at the start of the line in url variable declaration (line 4), if you want to make a request to the external server.
Your request was made to the local webserver http://localhost/jasper/... and you've received a 404 (not found) error.

Download Image Using Fetch In ReactJs

I'm trying to download an image using fetch in reactJS. But whenever I call the function, I face the CORS error.
var image_trade_license = new Image();
image_trade_license.crossOrigin = "anonymous";
image_trade_license.src = "https://via.placeholder.com/150/92c952";
// get file name - you might need to modify this if your image url doesn't contain a file extension otherwise you can set the file name manually
var fileName_trade_license = 'trade_license';
image_trade_license.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
var blob_trade_license;
// ... get as Data URI
if (image_trade_license.src.indexOf(".jpg") > -1) {
blob_trade_license = canvas.toDataURL("image_trade_license/jpeg");
} else if (image_trade_license.src.indexOf(".png") > -1) {
blob_trade_license = canvas.toDataURL("image_trade_license/png");
} else if (image_trade_license.src.indexOf(".gif") > -1) {
blob_trade_license = canvas.toDataURL("image_trade_license/gif");
} else {
blob_trade_license = canvas.toDataURL("image_trade_license/png");
}
$("#image1").append("<a download='" + fileName_trade_license + "' href='" + blob_trade_license + "'><button>Download Trade License</button></a>");
}
and I am facing this error (occured in browser Console) -
Access to image at 'https://via.placeholder.com/150/92c952' from origin
'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-
Allow-Origin' header is present on the requested resource.
via.placeholder.com/150/92c952:1 Failed to load resource: net::ERR_FAILED
First, Have you ever set mode: "no-cors" in fetch config? Like this:
fetch('https://via.placeholder.com/150/92c952', {
method: 'POST',
mode: "no-cors"
})
If you still receive CORS error. You can disable origin policy in Chrome to continue to call API that without CORS error with This Post
Or, This post could give you more knowledge about CORS in Web Browser.

Local image upload using TinyMCE editor and ExpressJS

I'm running application on my website and for some articles and reviews im using TinyMCE editor. Works perfectly, storing to DB also works.
But i have a need to add local images to articles and upon submitting a form i want to save them to dynamic location on server (based from where i save).
Can i even do this using expressJS and tinyMce editor?
I've tried setting needed stuff in tinymce.init method, I even have upload section when selecting Image in TinyMce UI, but as soon as i select image, i'm getting HTTP error 404. What i did to solve this, is to create POST route in express JS where i suppose i end up in, but i have no idea what i'm doing.
This is my TinyMCE init:
tinymce.init({
selector: '#tinySelector',
plugins: 'advlist autolink link code image lists charmap print preview textcolor media',
toolbar: 'undo redo | image code',
relative_urls: true,
document_base_url: 'http://www.example.com/',
images_upload_url: '/upload.php',
images_upload_hand: function (blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/upload.php');
xhr.onload = function () {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
}
});
Express route:
router.post('/upload.php', ensureAuthenticated, (req, res) => {
console.log('testis');
});
Php file:
<?php
/***************************************************
* Only these origins are allowed to upload images *
***************************************************/
$accepted_origins = array("http://localhost", "http://192.168.1.1", "http://example.com");
/*********************************************
* Change this line to set the upload folder *
*********************************************/
$imageFolder = "/public/tinyImages/";
reset ($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])){
if (isset($_SERVER['HTTP_ORIGIN'])) {
// same-origin requests won't set an origin. If the origin is set, it must be valid.
if (in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)) {
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
} else {
header("HTTP/1.1 403 Origin Denied");
return;
}
}
/*
If your script needs to receive cookies, set images_upload_credentials : true in
the configuration and enable the following two headers.
*/
// header('Access-Control-Allow-Credentials: true');
// header('P3P: CP="There is no P3P policy."');
// Sanitize input
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
header("HTTP/1.1 400 Invalid file name.");
return;
}
// Verify extension
if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
header("HTTP/1.1 400 Invalid extension.");
return;
}
// Accept upload if there was no origin, or if it is an accepted origin
$filetowrite = $imageFolder . $temp['name'];
move_uploaded_file($temp['tmp_name'], $filetowrite);
// Respond to the successful upload with JSON.
// Use a location key to specify the path to the saved image resource.
// { location : '/your/uploaded/image/file'}
echo json_encode(array('location' => $filetowrite));
} else {
// Notify editor that the upload failed
header("HTTP/1.1 500 Server Error");
}
?>
I expect to select a file, see it in tinyMce editor, upon submitting saving image for start to some predefined path.

XMLHttpRequest endpoint blocked while signing S3 request because no HTTPS, eventhough everything is on HTTPS

I am trying to sign a huge video upload, because I want to upload it directly to S3. It works on localhost, but on my live site it fails to sign the request because of:
Mixed Content: The page at 'https://www.example.com/profile' was loaded
over HTTPS, but requested an insecure XMLHttpRequest endpoint
'http://www.example.com/sign_s3/?file_name=17mbvid.mp4&file_type=video/mp4'.
This request has been blocked; the content must be served over HTTPS.
I am hosting everything on heroku, every page is already using HTTPS and its not possible to open it in HTTP, because I redirect all traffic to HTTPS. I am using the letsencrypt SSL certificate.
So far I have no idea where to look, the only information I found, is that I need a valid SSL certificate, which I have.
Here is the JS function:
function getSignedRequest(file) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/sign_s3?file_name=" + file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('got signed request');
var response = JSON.parse(xhr.responseText);
console.log(response);
console.log('uploadFile', response.url)
uploadFile(file, response.data, response.url);
} else {
console.log("Could not get signed URL.");
}
}
};
//console.log('send');
xhr.send();
}
Right after the error in the console I see this console log:
Could not get signed URL.
which means it fails here:
if (xhr.status === 200)
On the server:
#app.route('/sign_s3/', methods=["GET", "POST"])
#login_required
#check_confirmed
def sign_s3():
if "localhost" in request.url_root:
file_name = str(current_user.id) + "local-profil-video." + request.args.get('file_name').split(".")[-1]
else:
file_name = str(current_user.id) + "-profil-video." + request.args.get('file_name').split(".")[-1]
file_type = request.args.get('file_type')
session = boto3.Session(
aws_access_key_id=app.config['MY_AWS_ID'],
aws_secret_access_key=app.config['MY_AWS_SECRET'],
region_name='eu-central-1'
)
s3 = session.client('s3')
presigned_post = s3.generate_presigned_post(
Bucket = 'adultpatreon',
Key = 'videos/' + file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
{"acl": "public-read"},
{"Content-Type": file_type}
],
ExpiresIn = 3600
)
if current_user.profile_video != None:
delete_file_from_aws("videos/", current_user.profile_video)
setattr(current_user, "profile_video", file_name)
db_session.commit()
return json.dumps({'data': presigned_post, 'url': 'https://s3.eu-central-1.amazonaws.com/mybucket/' + 'videos/' + file_name})
After many hours of researching I decided to rebuild this function and use AJAX get, which I am more familiar with. I also changed the way I pass/recieve the query string arguments to the best way, which is actually used in flask/python.
function getSignedRequest(file) {
$.ajax({
url : "/sign_s3/" + file.name + "/" + file.type,
type : "get",
success : function(response) {
console.log("success file up, follow", response);
var json_response = JSON.parse(response);
console.log(json_response);
uploadFile(file, json_response.data, json_response.url);
},
error : function(xhr) {
console.log("file up failed", xhr);
}
});
}
And on server side I changed how file.name and file.type are recieved:
# Sign request for direct file upload through client for video
#app.route('/sign_s3/<path:file_name_data>/<path:file_type_data>', methods=["GET", "POST"])
#login_required
#check_confirmed
def sign_s3(file_name_data, file_type_data):
#etc...
Now it works perfectly. I think they way I was recieving the query string arguments on the server was not correct, probably it would also work with the old getSignedRequest function (untested).

Categories

Resources