I am trying to upload a file. My application only has a Browse button and no place to send any file path. So I am unable to use SendKeys.SendWait(#"filepath"); I tried using JavaScriptExecutor but getting error while using the below code:
IWebElement upload = _driver.FindElement(By.XPath("//div[starts-with(#class,'addDoc') and contains(text(),'Browse')]"));
string filepath = #"C:/Users/../Amazon vs Walmart.pdf";
String script = "document.upload.value= " + filepath;
((IJavaScriptExecutor)_driver).ExecuteScript(script);
Runtime.evaluate threw exception: SyntaxError: Unexpected token :
Why am I getting the exception?
Interacting with file browsing windows is outside the scope of what the webdriver can do. When you click browse the browser passes you off to the OS to find the file. Javascript cannot act on these windows.
SendWait is used as a trick to pass the uri of the file to the open the window and return. If that is not working you will need to use something to interact with OS windows.
I personally use InputSimulatorCore to handle issues like this when working with IE, which has lots of these type of issues with file downloads.
Edit: If you control the application changing to a forms based upload will allow you to do the testing in Selenium and is the best option. If not you can also directly do a post to the upload endpoint.
There are multiple issues with the code you posted. First, you’re attempting to call ExecuteScript with invalid JavaScript. To wit, once your strings are concatenated, your JavaScript looks like this:
document.upload.value= C:/Users/../Amazon vs Walmart.pdf
Note that there are no quotes around the string you’re actually attempting to set. The syntactically correct JavaScript would be:
// Note carefully the quotes around the string literal.
document.upload.value='C:/Users/../Amazon vs Walmart.pdf'
To yield that, your concatenation code would need to look like this:
string script = "document.upload.value='" + filepath + "'";
The second issue is that you’re attempting to invoke uploading a file. Assuming the upload is accomplished by using standard HTML mechanisms, that means that somewhere on the page, there is am <input type="file"> element. It might be hidden, but it’s there somewhere on the page. To upload a file, you can use the SendKeys method on that element. The file upload case is one of the very few exceptions for SendKeys to the rule that elements to be interacted with must be visible to the user (at least with the most recent versions of browsers and browser drivers. If the application is using some non-standard upload mechanism, like a pure JavaScript implementation, or some sort of Flash component, then you’ll need to use some other method to communicate with that component.
Though I tried using AutoItX to upload file and it worked. Below is the code for the same -
to get AutoItX, I installed Nugget package - AutoItX.DotNet
AutoItX.ControlFocus("Open", "", "Edit1");
AutoItX.ControlSetText("Open", "", "Edit1", filepath);
AutoItX.ControlClick("Open", "", "Button1");
But still, I would like to explore using JS as well.
Related
I have a jQuery script in which I want to download a file which is located on some server after the user clicks on the link. On IE11 this works alright, as I simply make a call to:
window.open('file:///MyServer0001/SomeFolder/Tmp/ToiletFlush.log'
I know that for security reasons, Chrome doesn't allow to use the protocol file:/// . It is interesting because if I write myself this URL on the address bar he will show the file, however if I make a call for window.open() he just opens me a new empty window. Also, removing the file:/// , doesn't do anything on Chrome, it says that the page is not available
So right now I don't know how to make this work on chromium. I thought I could make a workaround by calling the controller function through a POST/GET , return a FileResult and download the file. This definitely works but I would like to know a simple way to do this directly only using jQuery/JavaScript.
Any Idea?
Try ASP.NET MVC FileResult:
View:
Download File
In Home Controller:
public FileResult GetFile()
{
//Read file content into variable.
string content=File.ReadAllText("filepath");
byte[] byteArray = Encoding.ASCII.GetBytes(content);
return File(byteArray, System.Net.Mime.MediaTypeNames.Text.Plain, "ToiletFlush.log");
}
Try this,
On Windows:
1. Find the local URL of your Chrome Install
2. From the Command Line launch Chrome w/ '–allow-file-access-from-files' prepended to it:
–allow-file-access-from-files C://...
On OSX, just type this in Terminal:
open /Applications/Google\ Chrome.app --args --allow-file-access-from-files
Using Google Chrome Canary is also possible:
open /Applications/Google\ Chrome\ Canary.app --args --allow-file-access-from-files
Or... You'll need to run your application on a local server.
I'm working on a continuing API project. The current issue at hand is to be able to download my data from the AtTask server in precisely the folder structure they exist in on the AtTask servers. I've got the folder creation working nicely; the data types between Document, Document Folder and Document Version seem to be pretty clear. I am a little disillusioned about the fact that extension isn't in the document object (that I have to refer to the document VERSION for that)... but I can see some of the reason for that from a design perspective.
The issue I'm running into now is that I need to get the file content. I originally through from the API documentation that I'd be able to get to the file contents the same way as the documentation recommends uploading it -- through the handle. Unfortunately, neither document nor docv seem to support me accessing the handle except to write a new file.
So that leaves me the "download URL" as the remaining option. If I build the UI strings from the API calls using my browser, I get a URL with https://attaskURL/document/download?ID=xxxx (and can also get the versionID and such). If I paste the url into the browser where I'm logged in to the user interface of AtTask, it works fine and I can download the file. If, instead, I use my C# code to do so, I get the login page returned as a stream for me to download instead of my actual file because I'm not authenicated. I've tried creating a network credential and attaching it to the request with the username and password, but to no avail.
I imagine there's a couple ways to solve this problem -- the easy one being finding a way to "log in" to the download site through code (which doesn't seem to be the usual network credential object in C#) OR find a way to access the file contents through the API.
Appreciate your thoughts!
It looks like you can use the download URL if you put a session id in the URL. The details on getting a session id are here (basically just call login and a session id is returned in JSON):
http://developers.attask.com/api-docs/#Authentication
Then cram it on the end of your document download URL:
https://yourcompany.attask-ondemand.com/document/download?ID=xxxx&sessionID=abc1234
I've given this a quick test and I'm able to access a document.
You can use the downloadURL and a sessionID IF you are not using SAML authentication.
I have tried it both ways and using SAML will redirect you to the login page.
In my project i will be having an link like
Download
I want the users to download files of different types. The file will be in the root folder. When i am clicking on the link it is displaying an error. This is the plugin to install in the chrome. If the user download this link and open then it will automatically add to the chrome.
How can i do this.
The file is not even downloading.
This isn't a valid path:
~/hello world.crx
The ~ character is for use server-side to denote the root of the application. Client-side it has no meaning. The browser doesn't know what the root of the application is (or what the application is at all), it's just sending requests to resources at addresses. And it doesn't know what to do with that address.
You'll need to either use some server-side logic to translate that path into a browser-useable path, or manually make it a relative or absolute path.
If the ASP.NET MVC Framework isn't translating this for you then you're probably using a version that requires a little more manual work for it. Try something like:
Download
(Note: This assumes the use of the Razor view engine. If you're not using that then you'll want to use whatever your view engine equivalent is.)
What you need to do is set up a directory online, where you can host the file.
I also see that in your aref you don't want to type the full path so denote it with a /hello_world.crx, but make sure that you've set up a base href:
<base href="http://yourdomain.com/something/">
Try renaming the file to remove any spaces e.g. "hello_world.crx" and then change the name in the link code to match.
if a webpage and the downloadable file is in the same location
(i.e)
SampleFolder->Download.html
SampleFolder->hello world.crx
then try the below
download
If the webpage and the downloadable file in different location
(i.e)
SampleFolder->Download.html
SampleFolder->Downloads->hello world.crx
then try the below
download
I would like to open a website in a user's default web browser, however since the url is user-defined I would also like to prevent them from doing anything other than opening a website.
I have seen people use Process.Start(url); to open a site in the default browser, but since the url is user-defined I want to be sure they don't enter something like a script location and execute it.
I also don't want to use Process.Start("iexplore", url); since I would rather open the link in the user's default browser.
Is there a way I can open a website in the user's default browser, without letting them launch any other process or command?
EDIT
For example, I don't want users to be able to enter C:\Windows\Notepad.exe into the Customer's Website field and open Notepad when they click the Website link
EDIT #2
I am not looking for a way to filter user's access online or have this substitute for property security. I am simply looking for a way to prevent users from launching any other application by entering in a bad url. If they enter "google" for a Customer's website, it should not throw an Open With file dialog, but instead launch the user's default web browser with the word "google" in the URL
You could look up the default browser from the registry. It's in several different places, but I think HKEY_CURRENT_USER\Software\Classes\http\shell\open\command would be a good place to look.
Extract the executable name from that, then Process.Start it with the user-entered URL as a parameter.
I found a way to do it, however I haven't tested to see if this will work on other operating systems
I get the Path for the DefaultWebBrowser from the registry and then use Process.Start(defaultBrowserPath, url);
public static void OpenWebsite(string url)
{
Process.Start(GetDefaultBrowserPath(), url);
}
private static string GetDefaultBrowserPath()
{
string key = #"http\shell\open\command";
RegistryKey registryKey =
Registry.ClassesRoot.OpenSubKey(key, false);
return ((string)registryKey.GetValue(null, null)).Split('"')[1];
}
Well, not really. What you could do is check whether it's a HTTP(s) URL, and whether the URL returns a text/html content-type - but not even that will help if the browser uses content sniffing (ignores content-type, tries to determine it from file content - IIRC IE6 does this, not sure what others).
Also, various browsers are susceptible to various security holes in malformed URLs (why does IE come to mind again?), so you may want to check for things like null hacks, EOL hacks, etc etc.
In the end, there is no perfect URL check - old/unpatched browsers will always be susceptible to some exploits, and that's not really something you can fix. You can, however, filter out most of them - whether it will be 80%, 99%, or 99.99%, depends on the amount of time you are willing to invest.
If I'm understanding you right, then there is no solution to the problem you describe. You're saying: how can I filter user-entered data (hopefully in the form of a Uri, but even a Uri is a very broad concept) to ensure that it's not malicious content. The answer is that without doing it manually, you can't.
http://here.dowloadmyvirus.com is a perfectly valid site Uri but you can never ever guarantee the content that will be served from there.
It needn't even be a Uri: if you hit Start/Run and type "iexplore c:\windows\notepad.exe" then (with IE9 RTM) I get my own local notepad.exe launched as a download. There's nothing to stop you pointing at a malicious script hosted online.
I'd suggest that you either need to limit access so that only a few trusted users can edit whatever data it is you're managing, or have an audit process in place to ensure that such content is validated before it's published.
I've worked out a way, which takes advantage of the fact that javascript runs in a sandbox.
Have a web-page (e.g. http://mydomain/LaunchPage.html) that is accessibly to your desktop application. Call it by putting your URL on the query string (so http://mydomain/LaunchPage.html?URL=http://www.google.com).
All the LaunchPage does is to use JavaScript to set the document.location.
<script>
/*
* Retrieve names values from the query string.
* Based on an idea from
* http://ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/Get_Query_String_Using_Javascript.shtml
*/
function queryString(key) {
args = window.location.search.substring(1).split("&");
for (i = 0; i < args.length; i++) {
keyValuePair = args[i].split("=");
if (keyValuePair[0].toUpperCase() == key.toUpperCase()) {
return keyValuePair[1];
}
}
return null;
}
document.Location = queryString("URL");
</script>
If the URL is set to a local file or something, then the JavaScript sandbox will prevent it being used.
You can now use the following code in perfect safety.
Process.Start("http://mydomain/LaunchPage.html?URL=C:\Windows\Notepad.exe")
EDIT Note that the HTML file could be installed alongside your application. If you have done this, the code to launch it would be something like:
Process.Start("c:\<InstallRoot>\LaunchPage.html?URL=C:\Windows\Notepad.exe")
I think you can check the url to confirm that it is a valid URL not a path of an executable file.
You can use regular expressions to validate the url, have a look here here.
Good luck!
It seems to me that you are worrying about something that is not in fact a problem. If the user could run a program rather than a URL from your app, then they could just as well run a program themselves. It's only a security concern if you accept input from some entity other than the logged on user.
I'm trying to download file from FTP using javascript, for which I created the following topic:
Is it possible to download file from FTP using Javascript?
From there I learned that I can use window.open('ftp://xyz.org/file.zip'); to download the file. It opens a browser new window, but the window closes immediately.
How I can I force it to stay open?
Actually I do all these in Silverlight application:
Here is the code:
HtmlPage.Window.Eval("window.open('" + url+ "', 'Download', 'height=500,width=800,top=10,left=10');");
I also tried this,
string targetFeatures = "height=500,width=800,top=10,left=10";
HtmlPage.Window.Navigate(new Uri(url), "_blank", targetFeatures);
But both results in same : it opens a window, and closes it immediately. I see it just for fraction of second!
I know this doesn't answer your question, and I'm sure you know all of this. I'm answering more because I don't see this point brought up often. :)
Silverlight has very limited support for client interactions. Javascript is a shim that in my opinion gets overused to try and bypass things that Silverlight was architectured against. It would have been very easy for Microsoft to include FTP support in Silverlight but it was excluded for a reason.
However, Silverlight has great support for webservice interactions. So the recommended way of getting a file would be to call a webservice that would do the FTP transfer for you and then send the contents down to the Silverlight application via the webservice. Possibly even processing it on the webservice side for any business logic etc.
Like I said, I suspect your requirement is to not use a webservice (to pass the bandwith cost onto the user most likely). But it'd be interesting to know more about your business problem instead of your technical problem for the solution you've chosen.
It closes because it triggers file download. You can open two windows - one for message and one to download file, but I thiunk user will know it is downloading...
If I were you, I'd open up a page that has whatever visual/UI stuff you'd want to show the user, and either have a META tag that redirects to the download URL, or has a javascript blurb to fire off said download. That way, your window will stay open, but the download will still start automatically.
to keep it open use
var test = window.open();
test.location = 'ftp://openbsd.org.ar/pub/OpenBSD/2.0/arc/kernels/bsd.ecoff';
and to not open any window use
window.location = 'ftp://openbsd.org.ar/pub/OpenBSD/2.0/arc/kernels/bsd.ecoff';
or make a normal link
Remember that a browser is not meant to "display" (visually anyway) the FTP protocol, and not all browsers will suport it. If you want to allow the user to download something, consider using a normal http:// protocol, and opening a window normally as others have suggested.
If you really need the download to be hosted via FTP, consider your backend ingesting (and caching) the file and return it to the user via http
There is nothing to be parsed on the browser's side, hence it closes. If you want to have the page open, you'll have todo something dirty. Like creating a html (or php) page and serve the content you want the user to see, then with a hidden i-frame which will call the FTP contents.
This way your user will see the content you want them to see, and the file is being downloaded.
I had the exact same problem, Silverlight opening a new window for downloading a file would flash a blank window up briefly and it would disappear again without the file download occurring.
This seemed to happen in IE 8 (not 9 and up) and could be fixed by going into Tools->Internet Options->Security then click Custom level... (for whatever zone your site would be in) and go to Downloads->Automatic prompting for file downloads and make sure this is Enabled (I also have File download enabled below that). This Automatic prompting for file downloads setting seems to be absent from IE 9+.
Another workaround is to not open in a new window, if the target url immediately downloads a file it won't change the current window so there's no difference in UX:
HtmlPage.Window.Navigate(new Uri("\download.ashx?fileid=12345"));