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.
Related
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)
I'm attempting to make a basic .NET API for managing a collection of media (images and videos).
I have configured the webroot to be a folder called "site", and within that folder is a folder called "media" where these files are stored. I can access a test media file that is saved in /site/media/Smush.jpg by loading https://localhost:5001/site/media/smush.jpg - this serves the image as expected.
I have created a method that receives a POST request containing form data from my frontend, and this method saves the file to the webroot using a filestream, code below:
[HttpPost]
[Route("/media/add")]
public async Task<HttpResponseMessage> MediaAdd()
{
try
{
//get the form
var form = HttpContext.Request.Form;
//if there's a route, add it into the filepath, otherwise leave it out and have the filepath go straight to media (this prevents an exception if route is blank)
string filePath = form["route"] == "" ? Path.Combine(_hostingEnvironment.WebRootPath, "media") : Path.Combine(_hostingEnvironment.WebRootPath, "media", form["route"]);
//get the first (should be only) image - DO WE WANT TO BE ABLE TO ADD MULTIPLE IMAGES? PROBABLY TBH
IFormFile image = form.Files.First();
if (image.Length > 0)
{
//check the directory exists - create it if not
if (!Directory.Exists(filePath)) {
Directory.CreateDirectory(filePath);
}
using (Stream fileStream = new FileStream(Path.Combine(filePath, form["filename"]), FileMode.Create))
{
await image.CopyToAsync(fileStream);
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
else {
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
catch (Exception e)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
My frontend submits a route, filename and the media file, and this is used to save the image. This all works fine; I can submit an image with the path "test" and the name "test.jpg", and the API correctly stores the file at /site/media/test/test.jpg. I can view the file in the solution and see a preview of the image, as with Smush.jpg.
However, attempting to load https://localhost:5001/site/media/test/test.jpg results in a 404. Why is this the case? Can I not add files into the webroot through code and have them be accessible as static files as if I added them to the solution in my IDE? Are there any alternative ways of handling this?
I am using .NET 5.0, and have
app.UseStaticFiles(); in Configure() in Startup.cs.
Sorry if this is a duplicate, but I couldn't find anything else like this.
EDIT:
On checking things again, it seems like rather than my files being at https://localhost:5001/site/media, they are simply in https://localhost:5001/media. I am not sure how I was able to access Smush.jpg at https://localhost:5001/site/media/Smush.jpg before.
It seems as though the webroot is not included as part of a URL to access files within it.
As it is now, I have got what I was looking for it to do.
Well first a security concern as also #Heinzi pointed out...
string filePath = form["route"] == "" ? Path.Combine(_hostingEnvironment.WebRootPath, "media") : Path.Combine(_hostingEnvironment.WebRootPath, "media", form["route"]);
What if the user sends form.route == "../../" and instead of image he updates the appsettings.json file ?
Check this out and have that in mind if you're planing to release this code to a production environment and make sure you only accept image files.
On the other hand if you are serving static files from a folder different to wwwroot please use this configuration
Why the 404
It makes sense. You are under the controller/action paths. Going under the site url the engine does the following:
When you request https://localhost:5001/site/media/test/test.jpg the code tries to find the media controller and the test action. It is not looking for static files on the filesystem. Since there is no such controller/action pairs, it will not find anything and thus return 404 not found.
If you saved the files in https://localhost:5001/static/media/test.jpg outside of the mapped routes, you would be able to access it.
Look inside your code for:
MapHttpRoute
Which is used to configure how to identify controller actions which are not decorated with the [Route] attribute.
Security concern
When you want to upload a file, you should consider a better solution and not one that accesses directly your filesystem.
Possible options:
Blob storage on the cloud
Database blobs
Don't forget to sanitize the input with an antivirs or some similar solution.
I received a link to shared folder from e-commerce company. The link is public and not shared with my dropbox account directly.
How do I get an url to the image that I can pass to either DownloadAsync method of the same sdk or simply HttpClient and well ... download it?
Ideally it would be the same link I get when I click on the image when viewing that shared folder in a browser.
https://www.dropbox.com/sh/{folder_hash}/{file_hash_maybe}/{filename}?dl=0
This is what I have tried:
using Dropbox.Api;
using Dropbox.Api.Files;
...
var accessToken = "abracadabra";
var sharedFolderUrl = "https://www.dropbox.com/sh/{folder_hash}?dl=0";
using (var dbx = new DropboxClient(accessToken))
{
var sharedLink = new SharedLink(sharedFolderUrl);
var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink);
// sharedFiles - has over 13,000 entries, I use cursor to get them all.
foreach (var file in sharedFiles.Entries)
{
if (file.IsFile)
{
// tried this, but:
// 1. it's crazy to loop through all
// 2. link.Response.Url gives me the same url to a shared folder for all items
var link = await dbx.Sharing.GetSharedLinkFileAsync(url: sharedFolderUrl, path: "/" + file.Name);
}
}
}
Using the GetSharedLinkFileAsync method is the right way to programmatically download a file from a shared link. It actually gives both the metadata (in the link.Response in your code like you mentioned), as well as the file data directly (not via a URL).
To access the file data, you can use any of the GetContentAs... methods documented under IDownloadResponse as returned by GetSharedLinkFileAsync. In your code, that would look something like: link.GetContentAsStreamAsync() (or whichever one you want).
Alternatively, if you want to download the entire folder from the shared link, you can use the URL parameters documented in this help center article. (That may fail for very large folders though.)
I am trying to open a pdf file using the below working code I previously used on another app,
but this time I am getting System.Runtime.InteropServices.COMException when the flow hits this line: Windows.System.Launcher.LaunchFileAsync(pdffile);
What is the meaning of this exception and how to get rid of it?
Please note that without caring about this exception (disabling it),
the file still cannot be opened.
Please note: the file exists in my isolated folder (checked with wpowertool),
I tried with 2 different files so it shouldnt be a matter of file corruption.
public void openFile(string options)
{
System.Diagnostics.Debug.WriteLine("options: " + options);
string optVal = JsonHelper.Deserialize<string[]>(options)[0];
asyncOpen(optVal);
}
public async Task asyncOpen(string filename)
{
filename = filename.Substring(2, filename.Length - 2);
filename = filename.Replace("//", "/").Replace("/", "\\");
Windows.Storage.StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
Debug.WriteLine("local: " + local.Path);
Windows.Storage.StorageFile pdffile = await local.GetFileAsync(filename);
Debug.WriteLine("pdffile: " + pdffile.Name);
//// Launch the pdf file.
Windows.System.Launcher.LaunchFileAsync(pdffile);
}
this MSDN post belongs to me. Yes, the file is installed and I have acrobat reader.
Please note that this C# code is a phonegap/cordova plugin which is called via javascript in my hybrid application.
Pay attention to the remarks in this MSDN Article - Launcher.LaunchFileAsync(IStorageFile):
The calling app must be visible to the user when the API is invoked.
This API must be called from an ASTA thread (also known as a UI
thread).
Huge ups to the OP for sharing the solution. The following code should help others get around this issue:
Deployment.Current.Dispatcher.BeginInvoke(() => { asyncOpenFile(options); });
I have a solution that grabs two files and compares them to see if they are the same or not. The sourceFilePath and destFilePath are both on my computer, but I want to be able to use the same solution to get files if they are on a different server. I will be able to test them by setting the parameters for the sourceServer and _destServerList to localhost. How can I make the solution use the file from the relative source server?
edit: I am using localhost for testing purposes before the solution is deployed.
This my current solution:
public class blarto
{
private Server homeServer;
private string homePath;
private ServerList awayServers;
private string awayPath;
private bool ExecuteCommand()
{
if (File.Exists(awayPath))
{
GetSum(homePath);
GetSum2(awayPath);
if (GetSum != GetSum2)
{
Console.WriteLine("they are different.");
return false;
}
else
{
Console.WriteLine("they are the same.");
return true;
}
}
else
{
Console.WriteLine("The destination file does not exist.");
return false;
}
}
}
Assuming you have access to the servers, you could use a UNC path. Something like:
\\your-server-name\share\path\to\file.txt
or
\\your-server-name.domain.com\c$\path\to\file.txt
Otherwise, your web server is going to have to serve up the files. You'd have to build a small single-page web application or HTTP handler that takes a relative path, goes and looks at the appropriate place on the file system it's running on, load the file as a Stream or byte array and write it out to the response stream (with appropriate content type and length headers). IIS will need to be able to handle the MIME type of the document.
The client will have to hold onto it in memory or write it to somewhere temporarily, which may force you to rethink your CRC implementation. All of this is amazingly insecure (you could theoretically give everyone access to every file on that server).
Alternatively, you could make the root folder of the files you need to compare a virtual directory, and then allow that directory to be browsed (an IIS setting). Then something like http://localhost/root/path/to/file.txt might work, but again, not secure at all.
It sounds to me like the file is on your localhost for testing, but will be on the server once you deploy.
If that is the case, start with the relative url of the file: _srcFile = /uploads/testfile.txt;
From that, get the real location using Server.MapPath:
var testFile = Server.MapPath(_srcFile);
Note: MapPath is also defined in HttpServerUtility.