Trying to upload a file with a HTML input element via Selenium/ChromeDriver.
If the file is a local file everything is OK.
But I need to upload from a URL. In that case the driver throws an error.
If I upload the URL with chrome manually (click on "Select file" and paste the URL as filename and click OK) the upload works as expected.
HTML:
<input type="file" name="file1">
C# code:
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("<URL HERE>");
var input = driver.FindElement(By.Name(name));
ele.SendKeys("C:\\pic.png"); //works because local file exists
ele.SendKeys("https://wikipedia.org/static/favicon/wikipedia.ico"); //fails
Exception:
OpenQA.Selenium.WebDriverException: "invalid argument: File not found : https://wikipedia.org/static/favicon/wikipedia.ico
(Session info: chrome=92.0.4515.131)"
I found out that the exception is thrown because the drivers DefaultFileDetector cant resolve it to a file.
So I tried to implement my own FileDetector and assign it to the driver:
var allowsDetection = driver as IAllowsFileDetection;
if (allowsDetection != null)
{
allowsDetection.FileDetector = new DummyFileDetector();
}
DummyFileDetector:
class DummyFileDetector : IFileDetector
{
public bool IsFile(string keySequence)
{
return true;
}
}
But DummyFileDetector.IsFile is never called (it seems that allowsDetection.FileDetector = new DummyFileDetector() does not change the FileDetector of the driver).
I don't want to download the file and then upload it (if that is possible). As said manually set the URL in the file selection dialog does the trick, but not with Selenium.
Any ideas?
I searched many questions here and on other internet resources, and found that the only way to upload a file from external URL with driver.SendKeys() method is first to download it to your local disk and then upload with driver.SendKeys()
Proof
I've never used C# before, but I think a really simple way to go around this is downloading the file, reuploading it, then deleting it. I'm sure you can do it in C#. I understand in selenium python it is pretty simple to do that, I don't think python code would be helpful here though (lol)
Related
Following code works to open an online URL. But it does NOT work for a web page (an HTML file) from local disk:
Question: It seems I'm missing something here. How can we make it for an html file from a local drive?
NOTE: No error is return, only the value of success variable is returned
false. I've verified that the HTML file exist by successfully opening it manually.
async void DefaultLaunch()
{
// The URI to launch. NOTE: It works only for online URLs, http://www.bing.com etc.
var uriTest = new Uri(#"file:///C:/DotNET2017/Test.html");
// Launch the URI
try
{
var success = await Windows.System.Launcher.LaunchUriAsync(uriTest);
}
catch(Exception ex)
{
string st = ex.Message;
}
}
Screenshot of uriTest value in debug mode:
You can't use "file///..." to lunch a local file.
you should use the launch file function and since it's an .html it will open in in the browser
first Get your IStorageFile from:
GetFileFromPathAsync
and then just launch your file:
Windows.System.Launcher.LaunchFileAsync(myStorageFile)
According to the documentation:
LaunchUriAsync(Uri)
Returns true if the default app for the URI scheme was launched; false otherwise.
So there must be an app registered to handle the scheme. There is no app in the system that is registered to handle the file: scheme, it is rather handled by the system itself which is not the app. So if you take this into account it returns false as expected.
You should rather use Launcher.LaunchFileAsync method. But please note that if you don't define the broadFileSystemAccess capability you will not be able to get the StorageFile out of the arbitrary path to send as the parameter for that method.
Question:
Does anyone know how to add a torrent to LibRagnar using a filepath to a torrent, instead of a Url? (LibRagnar is a libtorrent Wrapper)
libragnar = C#
libtorrent = C++
Alternatively if anyone knows How I can use Libtorrent To add the torrent to a session, But use a local file (Whilst still controlling Everything else using Libragnar).But I am not sure where to start with Libtorrent.
Reason For Problem:
I have to use a filepath because the Torrent Requires cookie login to access it. So I either Need to get Libragnar to use a CookieCollection when getting a torrent from a URL or make it use a local ".torrent" file.
Problem:
I am currently trying to use a filepath instead of URL and the Torrent Status gives an error:unsupported URL protocol: D:\Programming\bin\Debug\Tempfiles\File.torrent. Which wont allow me to start it.
Example:
var addParams = new AddTorrentParams
{
SavePath = "C:\\Downloads",
Url = "D:\\Programming\\bin\\Debug\\Tempfiles\\File.torrent"
};
Edit: Answer from Tom W (Posted in C# Chatroom)
var ati = new AddTorrentParams()
{
TorrentInfo = new TorrentInfo("C:\thing.torrent"),
SavePath = #"C:\save\"
};
Note About Answer: I attempted to edit Tom W's post and add the answer he gave me in the Chatroom, However I guess it got declined? But Since he was the one who helped me I wanted him to get credit, and also wanted anyone else having this issue, to have an answer. So I had to add the answer to the bottom of my question.
From the libtorrent documentation it appears that:
The only mandatory parameters are save_path which is the directory
where you want the files to be saved. You also need to specify either
the ti (the torrent file), the info_hash (the info hash of the
torrent) or the url (the URL to where to download the .torrent file
from)
Libragnar's AddTorrentParams appears to be a wrapper around add_torrent_params and has a property called TorrentInfo. I suspect if you avoid setting the URL, and set this property to an instance of TorrentInfo instead, you ought to get the result you want.
Disclaimer: I've never worked with torrents before, don't know this library, and don't work in C++.
I've got a local file with a temporary extension (.tmp) which contains valid HTML code. I would like to allow chrome to read this file as a basic HTML file.
When i load this file using chrome (e.g: file:///C:/file.tmp), chrome read it as a text file.
I'm using currently list of chromium command: http://peter.sh/experiments/chromium-command-line-switches/ but cannot find which command (if exists?) could let me do what i wish.
This question is not relative to csharp but i'm using a net application to load the file, here is the code:
var url = localFilePathUri; //e.g: file:///C:/file.tmp
string args = "--kiosk --allow-file-access " + url;
var test = System.Diagnostics.Process.Start("chrome.exe", args);
I could rename local file to use .html as extension but i would like to know if a more direct way exists?
Thank you!
I have the following code which works in Internet Explorer, but not in Firefox and Google Chrome.
public ActionResult LogoForm(HttpPostedFileBase file)
{
if (file != null)
{
string fpath = file.FileName;
if (System.IO.File.Exists(fpath))
{
// Logic comes here
}
}
}
In my View I have this:
#using (Html.BeginForm("LogoForm", "LogoEditor", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<text>Logo Image </text>
<input type="file" name="file" id="file" /> <text> </text>
<input type="submit" name="upload" value="Upload" />
}
In case of any file in Firefox and Chrome, the line 'if (System.IO.File.Exists(fpath))' always returns false! It doesn't find the file. Why so?
file.FileName contains the file path on the client computer, not on the server. You should not use it on the server. The reason this works in IE is because IE happens to send the full path to the file to the server and since you are running both the client and the server on the same machine it works. Chrome and FF for security reasons never send the file path. IIRC they send a dummy path to the server that doesn't exist anywhere. This won't work with IE neither when you deploy your application in IIS and access it remotely.
You should never rely on the path portion of file.FileName. You should only extract the filename and then concatenate it with some path on the server:
Like for example
[HttpPost]
public ActionResult LogoForm(HttpPostedFileBase file)
{
if (file != null)
{
string path = Path.GetFileName(file.FileName);
string fileName = Path.Combine(Server.MapPath("~/App_Data"), path);
if (File.Exists(fileName))
{
// logic comes here
}
}
}
I would also recommend you checking out the following blog post about uploading files in ASP.NET MVC.
When you say it returns false "in" Chrome and Firefox - it's not the browser executing your code, of course. It's the server executing code in response to a request.
Presumably they're giving the filename in some different format to IE. You should log what file.FileName is, and that should make it clearer what's going on. It's slightly alarming to see that you're just taking the exact filename posted by the browser - in the case of a relative filename it's probably not relative to the directory you want, and in the case of an absolute filename you're comparing whether a file that exists on the client computer exists in the same place on the server - which again, isn't a good idea.
EDIT: It sounds like you're interested in whether or not the file really exists on the client computer. Two points:
You can't tell, and File.Exists certainly isn't the right check. That's running on the server which doesn't have access to the client's file system, thank goodness.
You shouldn't care. Maybe the client doesn't really have a local file system - maybe it's simulating it from some cloud storage, or something like that. You're not meant to care about that: you've been given a request with some information about a "file upload" and that's what you should care about.
Just to add to what people have already said, if the user has added the file to the file input control, it must exist on the client's computer somewhere, since they've added it to the form on the website.
Once they've clicked submit, the HttpPostedFileBase inputstream property contains the bytes of the file, the filename is simply given so that you know what the name of the file is that was uploaded. As others have suggested use Path.GetFilename(string) to retrieve only the filename without directory path (if provided) and save that to your server. Generally, I will append some sort of timestamp to the file as to not overwrite a previous upload
Internet Explorer posts the original filename including the path for a type="file" input control, whereas other browsers just deliver the filename.
Since the browser usually does not run on the server, why do you want to check whether the full filename exists on the server?
Rather than attempting to use the path of what was sent into the controller (as others have mentioned, supported locally by Internet Explorer only), try the following:
if (file != null && file.ContentLength > 0)
{
// The fielname
var fileName = Path.GetFileName(file.FileName);
// Store the file inside ~/App_Data/uploads folder for example
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
// Other stuff
}
Is there a way to interact with a File Upload box in webdriver? The form field where the path gets put in is read only so I can't write to that.
You can do this without injecting JavaScript. You just need to get hold of the form field and type into it. Something like (using the Ruby API):
driver.find_element(:id, 'upload').send_keys('/foo/bar')
You can set the value of your input field using JavaScript. Considering that the id of the field is fileName the following example will set the value of the input to the file C:\temp\file.txt:
String script = "document.getElementById('fileName').value='" + "C:\\\\temp\\\\file.txt" + "';";
((IJavaScriptExecutor)driver).ExecuteScript(script);
In this example, driver is your WebDriver instance.
Please note that you have to use four backslashes (\) for Windows-like paths because you are required to pass double back-slashes to the JavaScript so you have to escape both with two additional slashes. The other option is to use a forward slash (e.g. "C:/tmp/file.txt") and that should also work.
For C#, SendKeys() works but you have to use \ in your file path instead of /
For example, the follow works :
string filePath = #"drive:\path\filename.filextension";
driver.FindElement(By.Id("fileInput")).SendKeys(filePath);
But the following doesn't work :
string filePath = "drive:/path/filename.filextension";
driver.FindElement(By.Id("fileInput")).SendKeys(filePath);
The problem I found is the upload dialog hangs the webdriver until closed.
That is, the element.click which invokes the upload dialog does not return until that upload dialog is closed. To be clear, upload dialog means an OS-native file selection.
Here is my solution (it's a bit complicated but *shrug* most workarounds for selenium webdriver problems must get complicated).
# presumes webdriver has loaded the web page of interest
element_input = webdriver.find_element_by_css_selector('input[id="uploadfile"]')
handle_dialog(element_input, "foobar.txt")
def handle_dialog(element_initiating_dialog, dialog_text_input):
def _handle_dialog(_element_initiating_dialog):
_element_initiating_dialog.click() # thread hangs here until upload dialog closes
t = threading.Thread(target=_handle_dialog, args=[element_initiating_dialog] )
t.start()
time.sleep(1) # poor thread synchronization, but good enough
upload_dialog = webdriver.switch_to_active_element()
upload_dialog.send_keys(dialog_text_input)
upload_dialog.send_keys(selenium.webdriver.common.keys.Keys.ENTER) # the ENTER key closes the upload dialog, other thread exits
Using python 2.7, webdriver 2.25.0, on Ubuntu 12, with firefox.
I am in search of 3rd party libraries too,
Unless there is no any other Window Then this works for me :
in C# add reference for System.Windows.Forms
using System.Windows.Forms;
string url = "http://nervgh.github.io/pages/angular-file-upload/examples/image-preview/";
string path = #"C:\Users\File_Path";
IWebDriver d = new ChromeDriver();
d.Navigate().GoToUrl(url);
d.FindElement(By.XPath("//input[#type='file']")).Click();
hread.Sleep(5000);
System.Windows.Forms.SendKeys.SendWait(path);
System.Windows.Forms.SendKeys.SendWait(#"{Enter}");
in my case i can upload file like solution that write hear but dialog window stuck the process, the driver cant reference to close this window, so i kill him manually:
foreach (var p in Process.GetProcessesByName("chrome"))
if (p.MainWindowTitle.ToLower().Contains("open"))
p.Kill();
We can use following (ruby API)
#driver.find_element(:xpath, "html/body/div[1]/div[2]/div[1]/form/div[4]/div[7]/table/tbody/tr[1]/td[2]/input").send_keys "C:\\Users\\Public\\Pictures\\Sample Pictures\\Chrysanthemum.jpg"
This is helped me to upload image.