I am currently working on an AngularJS project with a server backend written in PHP. The frontend and backend communicate entirely in JSON, however, there is an export scenario where the server's output is not JSON encoded but instead a (text or binary) file.
The web application cannot just redirect the client's browser to a download URL as the server requires custom headers in the HTTP request (i.e. an API key) to serve the file. Therefore, I am using $http in AngularJS to initiate an AJAX request. Here is what happens:
File generation on the server side (using PHP with Slim framework):
$export = $this->model->export_cards($project_key);
$this->app->response()->status(200);
$this->app->response()->header("Content-Type", "text/plain");
$this->app->response()->header("Content-Disposition", "attachment; filename=\"export.txt\"");
$this->app->response()->header("Last-Modified", date("r");
$this->app->response()->header("Cache-Control", "cache, must-revalidate");
$this->app->response()->body($export);
$this->app->stop();
This is what happens on the client side (so far):
$http({
method: "get",
url: "/server/projects/cards/export_cards/" + $scope.key,
headers: {
"X-API-Key": session_service.get("api_key")
}
}).then(
function(response)
{
// Success, data received
var data = response.data; // This variable contains the file contents (might be plain text, or even binary)
// How do I get the browser to offer a file download dialog here?
},
function(response)
{
// Error handling
}
);
I successfully receive the file contents in the AngularJS frontend and store them in a variable data. How do I get the browser to display a file download dialog?
The solution must work in Internet Explorer 10+ and reasonably recent versions of Firefox, Chrome and Safari (only desktop versions).
What is the best way to achieve this?
Thank you for your help and let me know if I need to provide any additional information.
Peter
I'm not sure this is possible.
Could you either:
Supply the API key directly, eg:
location.href = "/server/projects/cards/export_cards/" + $scope.key + '?api_key=' + session_service.get("api_key");
Or, have your API return a temporary, time-expiring URL for the file download, and then use location.href to access this URL.
Related
I already have a published app in both iOS and Android using Cordova. I'm using PHP scripts to retrieve and send data from server. Both platforms use same PHP script. I send data using XML. And call this script using AJAX.
a sample ajax call :
jQuery.ajax({
url: 'http://www.example.net/example.php', //load data
global: false,
type: "POST",
dataType: "xml",
async: true,
beforeSend: function() {
$('#loading').show();
},
complete: function(){
$('#loading').hide();
},
success: loading_complete_list,
error: errorfunc
});
Problem is I have to send some platform specific data. That means I need to send some specific data for ANDROID. I can't change app code as user may or may not update the app. So I have to change the PHP script such a way that it'll detect the ajax requesting platform or browser and send specific data. So far I know that iOS and Android uses specific webview such as safari or chromium. So if I can at least detect the requesting browser I can detect the platform.
Please remember I can't change app code as it's already published and I can't force user to update. Thus it has to be detected using the PHP script.
I tried searching detect browser using php for ajax call, but no luck so far. Is it possible to detect browser / platform through ajax call in PHP? If so then how?
echo $_SERVER['HTTP_USER_AGENT'] . "\n\n";
$browser = get_browser(null, true);
print_r($browser);
OK the title doesn't give much a way so let me explain my very strange set-up.
Two servers are involved:
website: remote
localhost: local machine
The workflow is as follows:
The site calls localhost via cross-domain AJAX
In response localhost dynamically creates a ZIP file via PHP's ZipArchive lib
localhost conveys the raw data that comprises the archive as the AJAX response
The request is made and the archive is made - all good. The archive is openable, all good. What I'm stuck on now is how to convey that archive as the AJAX response, such that it can be "put together again" (à la Humpty Dumpty). When I do this currently (via file_put_contents()) it errors on opening, saying it's invalid. Currently I'm just outputting the archive's raw data:
echo file_get_contents('path/to/archive.zip');
This is fine, but sends garbled characters in the response. I don't know much about encoding and headers, so apologise if this seems obvious.
For the response, should I be looking to convert it to binary, or sending certain headers etc? I tried sending the multipart/form-data header, but no dice. Headers aren't my strong point.
Please note cURL is not an option in this scenario, else I'd be laughing.
You have to read the zip file as a binary data with Blob javascript class.
This is a code snippet from Mozilla documentation
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
var blob = new Blob([oReq.response], {type: "application/octet-stream"}); //
// you have nothing to do with the blob...
// ...
};
oReq.send();
Then send this file (blob) with POST method to your destination
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
// Uploaded.
};
oReq.send(blob); //the blob that you loaded
you can read more in the documentation by Mozilla :https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
This might sound trivial for some of you, but I need to be sure...
I simply need to use dropbox for 2 things :
upload image files via php from my web server with the possibility of creating folder (as I would do on a normal web server) or sync folders from my web server to dropbox via rsync;
display these image files in a web page
I have downloaded the api sdk, then run into the 64bit exception error, then invalid redirect-uri...
So I would really appreciate if someone can reply to my 2 questions above and point me to a good example to just do that.
I solved it in another way. Rather than displaying the raw-file I use the API to generate Direct Download Link. This will give me a weblink that I then modify by adding a "raw=1" and subsitute the "dl=0" with "dl=1". This new link than then be used as the source for a normal html image.
As per above suggestions
import dropbox
import json
import httplib, urllib, base64
access_token='your token'
client = dropbox.client.DropboxClient(access_token)
url = client.share('test.jpg',short_url=False)
imageurl = url['url'].replace("dl=0","raw=1")
body = {
"url":imageurl
}
print json.dumps(body)
headers = {
# Request headers
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': '00759a20e705487a91e4db51b80bdfa7',
}
params = urllib.urlencode({
})
try:
conn = httplib.HTTPSConnection('api.projectoxford.ai')
conn.request("POST", "/emotion/v1.0/recognize?%s" % params,json.dumps(body), headers)
response = conn.getresponse()
data = response.read()
print(data)
conn.close()
except Exception as e:
print("[Errno {0}] {1}".format(e.errno, e.strerror))
i have some fields in panel. am sending user entries to the server using ajax request. In server side am using php to generate pdf[using tcpdf] file based on the entries made by user.
below is the code snippet of ajax request.
Ext.Ajax.request({
url: 'tcpdf3.php',
method : 'POST',
params : {
fromDate : Ext.encode(Ext.getCmp('FromDate').value),
username : Ext.getCmp('uname').value
}
success : function(){
// how to handle byte response giving by server . i.e want to download the pdf file(byte stream response) generated by server.
}
failure : function(){
}
});
ajax request carrying user entries is going to server correctly. And in server side the php file "tcpdf3.php" will give byte strems as response(i.e pdf file),upto this all is working fine. Am finding difficult how to handle the byte stream response given by server.i.e i want to download the pdf file generated.
below is the response given by server.
can someone please help me out of this.
I'm trying to create a simple RSS reader with Phonegap and jQuery.
I am following this tutorial: http://visualrinse.com/2008/09/24/how-to-build-a-simple-rss-reader-with-jquery/.
I've managed to get this working just fine when I try out the code in my browser. The php-file fetches the feed and outputs it just like I expect it to. But when I run the same file from within my compiled Phonegap application the ajax-request just returns the contents of the php-file (the php-code, not the executed result).
I've spent hours Googling this and tried numerous tutorials and tweaks. I found no solutions in the offical Phonegap forums either. What am I doing wrong? The problem seems to be PHP not responding to the request. I've tried to move the php-file to a different domain but the result is the same, it works in my browser but not in the compiled app.
Here's the jQuery code that initiates the ajax-code:
function get_rss_feed() {
//clear the content in the div for the next feed.
$("#feed_content").empty().html('<img class="loader" src="js/images/ajax-loader.gif" alt=""/>');
$.ajax({
url: 'http://192.168.1.7/rssApp/www/rss-proxy.php?url=http://www.nytimes.com/services/xml/rss/nyt/GlobalHome.xml',
success: function parseRSS(d) {
//find each 'item' in the file and parse it
$(d).find('item').each(function() {
//name the current found item this for this particular loop run
var $item = $(this);
// grab the post title
var title = $item.find('title').text();
// grab the post's URL
var link = $item.find('link').text();
// next, the description
var description = $item.find('description').text();
//don't forget the pubdate
var pubDate = $item.find('pubDate').text();
// now create a var 'html' to store the markup we're using to output the feed to the browser window
var html = "<div class=\"entry\"><h2 class=\"postTitle\">" + title + "<\/h2>";
html += "<em class=\"date\">" + pubDate + "</em>";
html += "<p class=\"description\">" + description + "</p>";
html += "<a href=\"" + link + "\" target=\"_blank\">Read More >><\/a><\/div>";
//put that feed content on the screen!
$('#feed_content').append($(html));
});
$('#feed_content img.loader').fadeOut();
}
});
};
Here's the rss-proxy.php that loads the XML from the url and outputs it:
<?php
// PHP Proxy
// Loads a XML from any location. Used with Flash/Flex apps to bypass security restrictions
// Author: Paulo Fierro
// January 29, 2006
// usage: proxy.php?url=http://mysite.com/myxml.xml
$session = curl_init($_GET['url']); // Open the Curl session
curl_setopt($session, CURLOPT_HEADER, false); // Don't return HTTP headers
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Do return the contents of the call
$xml = curl_exec($session); // Make the call
header("Content-Type: text/xml"); // Set the content type appropriately
echo $xml; // Spit out the xml
curl_close($session); // And close the session
?>
I've finally managed to solve this!
It turns out that you need to whitelist the server you wish to request from your PhoneGap application in Xcode if you want to do requests to a certain domain (be it your localhost or whatever).
The reason that I didn't found this out earlier was that I didn't check for errors in the ajax response. Once I did that I got the http status code 401 (Unauthorized) and error message "Whitelist rejected".
To fix this I opened the file PhoneGap.plist in my project and under the key ExternalHosts i added a new item with the value: *.localhost.
I also changed the ajax url to:
url: 'http://localhost/rssApp/www/rss-proxy.php?url=http://www.nytimes.com/services/xml/rss/nyt/GlobalHome.xml'
I compiled and run the application on the iOS Simulator and my localhost server responded with a perfectly successful ajax response!
For every external host that you wish your application to connect to you must add it to the list of ExternalHosts. For example if you wish to access an API on http://google.com/maps/api.php you must add *.google.com to your list.
Kind of annoying when you try to figure out why the server isn't responding, but I guess it's good for security reasons. Hope this helps someone else out there who's struggling with simple ajax requests from their PhoneGap application!
It looks like you are running your server locally (based on the 192.168.x.x IP address) which means that only devices connnected to your network can access it. You could connect the phone to the same wifi network as your computer as a temporary fix. But you're going to need to host this on a real server for it to be accessible over the internet.
You could also forward port 80 on your router to this IP address and then use your actual IP address (see whatsmyip.org) in your request url. But that's not a really stable solution.