I have been doing a lot of research and have yet to find a viable solution for the following. I asked a more specific question here) but due to the lack of answers or comments, I decided to ask a more generalized question that may be applicable to more people.
Anyway, dropzone.js allows you to create a file upload with js. Below is a snippet of code that does just that:
var myDropzone = new Dropzone(document.body, {
url: "/" // Not sure what to put here...
});
Where the url: "" would be equivalent to the action="" in a form. Most examples you can find have url: "upload.php" however I am trying to upload the images to firebase. Is there a way to run js for the file upload instead of php? perhaps url: "upload.js"? That wouldn't work but just to show what I mean. Or is there a way to upload images to Firebase with PHP? I am not quite sure how to proceed.
Here is what dropzone.js says about the URL attribute, I just don't understand it fully:
URL: Has to be specified on elements other than form (or when the
form doesn't have an action attribute). You can also provide a
function that will be called with files and must return the url (since
v3.12.0)
You can't upload directly to Firebase Storage via some special URL that you can put in a web form. But you can easily implement an endpoint with Cloud Functions for Firebase with a little extra code you write that runs on the server side.
I have a short Gist that gives all the code that makes it happen.
You can watch the code in action in this tweet.
I hosted my web site via Firebase Hosting, but if you don't do that, you may need to set up CORS or something to be able to call from your page to Cloud Functions.
Related
I'd like to download the data from a URL (which is just a text file), and then be able to use the data in JavaScript, ideally adding each line of the text file to an element of an array.
I've looked around for a simple way to do this but can't seem find anything appropriate.
You're looking for AJAX! It's a API which allows you to submit a request in JavaScript. An easy library to help you get started is jQuery.
Say you want to fetch the contents of example.com/file.txt and display it in an alert:
$.ajax({
url: "https://example.com/file.txt",
}).done(function(r) {
alert(r);
});
AJAX is great because the request is asynchronous, meaning it doesn't have to slow down the loading of the rest of your page: it runs alongside your other code.
Further documentation on jQuery AJAX.
I'd like to send a request to a simple URL from my JavaScript, so that the base URL will NOT be added to the request URL. For example, the request should be sent to the following URL (without the base URL):
SAPEVENT:SOME_TEXT?2
I used the jQuery's $.ajax function in order to implement it, but without success.
Here is a JSFiddle for it:
http://jsfiddle.net/txb6tdjj/2/
The JS code:
function sendEvent(id) {
$.ajax("SAPEVENT:SOME_TEXT?" + id);
}
sendEvent(2);
I see the following error in the JS console:
XMLHttpRequest cannot load sapevent:SOME_TEXT?2. Cross origin requests
are only supported for HTTP. (jquery-2.1.0.js:8556)
I even set the parameter crossDomain: true, but it didn't help:
http://jsfiddle.net/auhx2v2v/3/
The JS code:
function sendEvent(id) {
$.ajax({
url: "SAPEVENT:SOME_TEXT?" + id,
crossDomain: true
});
}
sendEvent(2);
It ends up with the same error.
It works correct in the HTML like this:
http://jsfiddle.net/1f6npcn2/2/
The HTML code which works correctly:
<FORM action="SAPEVENT:PRESS_ME">
Click on me to send an event!
<INPUT TYPE="submit" VALUE="Press me to send an event!"/>
</FORM>
But I need to implement it in JavaScript, so that a request parameter can be set dynamically in the URL in JavaScript.
Do you know how to implement it in JS so that the request will be sent to the URL SAPEVENT:SOME_TEXT?2 without the base URL?
Additional information about used browsers: The error is shown only in Chrome. IE and Firefox do not show an error, but they also don't send the request.
Additional information for the SAP guys: I know there is a SAP Note 191908 which states that it's impossible, but a colleague has confirmed that he has successfully tested such functionality in an HTML page which used the same code as I copied above (see the HTML code above and http://jsfiddle.net/1f6npcn2/2/). So the SAP Note is wrong. I know how I can implement this functionality in HTML, but I don't know how I can implement it in JS. That's the problem.
I have no experience of working with SAP but I think you are missing a crucial part here.
In the samples you gave SAPEVENT:CLICK_ON_ME isn't a http url at all but rather it would invoke whatever handles the SAPEVENT-protocol on the local computer with the parameter CLICK_ON_ME. I'm guessing that you have some sort of client installed on your computer that does this for you (how do I create my own URL protocol? (e.g. so://...) contains some more information on how this is accomplished).
The reason your error-message talks about crossdomain-stuff is probably because it tried to interpret it as host:port.
So in other words, since this isn't a http url there isn't a webserver working on the other end so you can't do ajax-requests against it.
The SAPEVENT: stuff is not handled by any web server. The SAP GUI uses an embedded Internet Explorer and registers a custom protocol handler. There is no use in trying to use ajax techniques since you need to reach the container of the client, not the server. To reiterate: You do not want to "send a request" anywhere, you want to convince the browser that a certain local navigation event happened". SAP Note 191908 contains more information on that topic.
No idea about SAP Views, but to me this seems like a usual behaviour on webservers. I presume that SAPEVENT gets parsed by the server during the runtime to a more regular URI. Only the views get parsed, not the resources like CSS and JS, so the SAPEVENT placeholders in the JS file don't get parsed and the JS interpreter will not accept it as a valid URI. One of the common ways of solving this, is to create either a hidden form in the HTML or just a hidden input containing the server-generated values you are needing. For example
SAP View:
<input type="hidden" id="my_event_url" value="SAPEVENT:PRESS_ME">
JS:
function sendEvent(id) {
$.ajax({
url: $('#my_event_url').val() + '?' + id,
crossDomain: true
});
}
sendEvent(2);
I finally implemented it in JavaScript. Thanks go to this web page.
I modified the solution which was shown in this web page in order to add a link instead of a form in JavaScript.
This is the working solution in JS:
var targetUrl = "SAPEVENT:SOME_TEXT?2";
function sendSapEvent(targetUrl) {
var link = document.createElement("a");
link.setAttribute("style", "display:none;");
link.setAttribute("href", targetUrl);
// Move the click function to another variable
// so that it doesn't get overwritten.
link._click_function_ = link.click;
document.body.appendChild(link);
link._click_function_();
}
sendSapEvent(targetUrl);
You can find it also in this JSFiddle: http://jsfiddle.net/708r95p0/6/
It works! It sends a request to the URL sapevent:SOME_TEXT?2
I decided to use a link instead of a form element, bacause I couldn't pass the request parameter using a form.
I want to access url of file which user select through pop up file directory navigation window. My browse button tag is:
<input type="file" id="loadFile"/>
On the back end, i can access the file url in javascript, but not sure how to do it in PHP.
You have to have the correct enctype for the form.
Otherwise, you utilize the $_FILES super global.
This is covered extensively in the PHP Manual regarding uploads.
The original filename is available in $_FILES['load file']['name']
Since it seems that you actually want a way to have the user provide a url to a file, the way to handle that is to simply implement a text input and accept the url there, and process the url on the server, using an HTTP client that fetches and stores the file on the user's behalf.
For years people have been using the curl extension, which is fast and highly functional. There are also a number of client libraries written in php like Guzzle.
I'm currently creating an image hosting script and so far so good. I've used several plugins to create the local uploading process with drag & drog + AJAX which works totally fine. Now I've moved to the part where I need to create the remote uploading process with jQuery AJAX and a PHP script to handle the whole thing.
How it's gonna work
My thought are like this: There is a big box in the middle of the page that accepts the URLs to be remote uploaded. Once valid URL(s) are passed into the text area, they will be immediately sent to the server side script via jQuery AJAX. It's bound with a keyup event.
This is how it looks like: http://i.imgur.com/NhkLKii.png.
The "HERE COME THE URLS" part is already a text area - So that part's already done.
Where I need help
The issue with this whole situation is: Once there are valid URLs pasted into the text area, those must be immediately be converted to some sort of box which also includes an uploading progress. Something that looks like this (copied from the local uploading part): http://i.imgur.com/q7RyDmb.png
It was easy implement the progress indicator for the local uploading, since it was a feature offered by the plugin I've used, but I don't know how to indicate the progress of remote uploading, which is totally being made from scratch.
So this is how I've imagined the logic to flow:
User pastes some URLs into the text area
There is a client-side check to validate the pasted URLs
Validated URLs are send to upload.php on keyup (?)
URLs are being processed
While the upload goes on, we show the users the progress in the knob (?)
PHP script finishes the process and returns back the uploaded URLs
I update the page in the AJAX success callback to display the uploaded files
So, the two process flows marked with (?) are unclear to me - I don't know how to achieve those...
What I have tried
Well, I didn't just come here and ask you to do everything for me, but I've come across a dead end and I don't know how to continue. What I've done so far is collect the URLs from the text area, and if there are multiple URLs separated by a line break (\n), I simply use split to get an array of pasted text and then use another function inside the loop to validate if they are URLs. If there is no line break detected inside the text area value, then I simply check the one line that was provided. On each case, I send the whole text area to the PHP script, because I don't know how to get rid of the invalid URLs in jQuery. I've created a function called debug() in PHP which stores anything into a debug.log file and this is what I'm getting (in one try) when I paste something into the text area:
https://www.google.com/https://www.google.com/
I paste https://www.google.com/ once in the text area, but it gets logged twice in the PHP side and I can't determine why.
This is how my jQuery looks like:
// Remote upload
var char_start = 10;
var index = 0;
var urls = $('.remote-area');
var val_ary = [];
urls.keyup(function(){
if (urls.val().length >= char_start)
{
var has_lbrs = /\r|\n/i.test(urls.val());
val_ary = urls.val().split('\n');
if (has_lbrs)
{
for (var i = 0; i < val_ary.length; i++)
{
if (!validate_url(val_ary[i]))
{
val_ary.splice(i, 1);
continue;
}
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: {
upload_type: 'remote', // Used to determine the upload type in PHP
urls: val_ary, // Sending the whole array here
},
});
}
else
{
if (!validate_url(urls.val()))
{
// Display an error here
return;
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: {
upload_type: 'remote', // Used to determine the upload type in PHP
urls: urls.val(), // Sending what's in the text area
},
});
}
}
});
The questions
So the final questions are:
How do I send my information correctly to the PHP script, only valid URLs and have them kind of "process-able" in my PHP script.
How do I indicate the progress of the upload?
If I was somewhere unclear during my question, please let me know, I'll try to reexplain.
Thank you.
Updates
09/12/2013
I think I have managed to solve the double-sending issue where my AJAX would send the same information twice to the PHP script. What I did was code in a delay anonymous function that sends the text area content to the PHP script after an user stops typing for 2 seconds. Once the user stops typing again, the timer resets and a new AJAX request will be made. So, I'm assuming that this issue has been solved. I'll come back to it if anything strange occurs.
Now I'm still left with the progress indicators part. I'd appreciate your thoughts on that one.
My new code: http://pastebin.com/SaFSLeE9
What you're looking for in terms of communicating progress back and forth is "pushing". That refers to the technique of server sending data to the client, rather than the other way around, which is the standard HTTP way of doing things.
You've got plenty of options available, as described in the explanatory Wikipedia article, though perhaps more relevant to this topic would be Comet. What happens is you trigger and $.ajax call just like the one you have now, but you set a very long timeout. That essentially gives the server a "channel" to send data back to the page whenever it's available.
So what you need is a .php on the server that is capable of handling long polling and will send data back to the page as the upload progress changes (probably in array form for multiple uploads). This article should get you started with some jQuery code. Just remember that this request doesn't go to upload.php. This request goes to a different script that deals solely with upload percentages and only returns data when that is available, it doesn't return immediately as all others scripts - the Ajax will happily wait for the data.
Also, don't separate your code like that with has_lbrs. One line or many are not distinct cases, one line is just an edge case of many lines. You're duplicating the code unnecessarily. What does the else case do that would break in the general case? Further, the "error handling" in the else case is misleading. The only error reporting you do is if there is only one line and it's wrong. What if you have two lines and they're both wrong? Your code will happily send an empty array to upload.php.
This is why I think you shouldn't separate your code like that, because then you'll split logic and not even notice it.
In my opinoin, the best way is to call your cURL script with ajax and use it to upload your files on remote server. You need ajax.js, curl.php, index.php (whatever name you want) on your app server. And image.php, class.image.php (whatever name you want) on your remote server.
Steps that I did for my app
1) I am going to upload an image from my index.php file. It will call curl.php file using ajax.js and the cURL file will check file's extension and all (for your app's security, make sure what you want to allow users to upload).
2) Now the curl file will upload the file to your pre defined temporary folder with the default file name.
3) Now if move_uploaded_file function (which I used in my script) run successfully, you can call your cURL function to send your data as post on your remote server, where image file will receive posts and will process further. You can keep your class in image.php or you can create two PHP files on your remote server, as you want.
4) Now in your class file, you should check file once again that it is image file (and whatever you want to allow) or not for better security. If file is good, process to rename it and add file into folder if you want to.
5) Add file's new name and folder name into your database by using remote database connection. So, cURL will show you result on the same page.
Now, why cURL? I prefer cURL because, you can add secret key or API for your communication to make it more secure, with if else conditions. Your remote server file which is going to receive all posts, will check if API == 'yourKey' then will process other wise it wont process and nobody will be able to send images on your server with bots and all.
I don't know that my answer is going to help you or not, probably my method is lengthy or not good for your app, but try to Google about cURL and you will understand what I am trying to say. Hope you like it and understood it. If any doubt, you can ask me any time.
It seems like this question is asked periodically and the common response is "You shouldn't do that with AJAX anyway. Just set the window location to the file."
But I'm trying to request a file that doesn't actually exist out on the server anywhere. It's dynamically generated (by a Django view) given the GET/POST context parameters. The file I want to retrieve via AJAX, and then save to the client machine, is a text file (csv).
I can currently get the text to the client machine (and can verify this by seeing it in logging or an alert) but cannot then figure out how to save this text to a file inside of the AJAX success callback fn.
Essentially, is this possible, is it something JS can do? That is, to open file save dialogs for "files" that are actually AJAX response text?
From the browser's point of view, it doesn't matter if the file exists or not, it's just a resource on a server that it's requesting. I think you're going to need to do some version of "Just set the window location to the file". If you set the content type in the header to something that the browser doesn't recognize, I believe it will ask the user if they want to save it.
As others mentioned, you can't do it only with JavaScript.
IMO the best option would be the Flash 10+ FileReference API.
There are some good JavaScript wrapper libraries like Downloadify that provide a JavaScript API to access those methods.
Give a look to this demo.
This isn't something JavaScript (and therefore jQuery or anything other JS framework) is allowed to do, for security reasons. You may be able to do what you want to flash or another route, but not JavaScript. Bear in mind Flash has it's own slew of security restrictions for this as well.
(Yes, IE can do this via an ActiveX object, but I'm not counting that as a "solution" here)
Basically, no. Javascript cant save anything to the local machine due to security restrictions. Your best bet may be to have a signed applet that the user can trust to write the file, or put it in a textarea that they can then easily copy and paste into a new file.
Could you not use the PHP rename() function for this, instead of just Javascript? Call to a PHP file and pass the name of the file you want to copy along with where as parameters?
I have the same problem. You can try this
<button id="Save">Save</button>
<img src="MakeThumbnail.ashx?Image=1.jpg" id="imgCrop">
$("#Save").click(function (e) {
url = $("#imgCrop").attr("src")+"&Action=Save"
e.preventDefault(); //stop the browser from following
window.location.href = url;
});