How to open a WPF Content Stream? - c#

Here's the code snippet
String str= ??????? // I want to assign c:/my/test.html to this string
Uri uri= new Uri (str);
Stream src = Application.GetContentStream(uri).Stream;
What's the correct way to do this? I'm getting "URI not relative" Exception thrown

Your problem is specific to WPF. See the Application.GetContentStream method.
You'll read that this method requires a relative URI. See "WPF Application, Resource, Content and Data files".

You have a file path - if you want to make it a URI add "file:///", ie. "file:///c:/my/test.html"

For local file URIs, you need to prefix it with:
file:///

I think you'll find your problem is that Application.GetContentStream is for a resource stream for a content data file that is located at the specified Uri. That is, deployed alongside an executable assembly.
If you look at: http://msdn.microsoft.com/en-us/library/aa970494(VS.90).aspx#Site_of_Origin_Files
You should find that the file:/// syntax as stated above is correct... But if you're going to open them you'll probably want some kind of switch to work out how to get the stream:
FileInfo fileToSave;
if (!existingFile.IsFile)
throw new ArgumentException("Input URI must represent a local file path", "existingFile");
fileToSave = new FileInfo(existingFile.LocalPath);
return fileToSave.Open(/* Args based on your needs */)
And similarly if it's a web URI:
if (!existingFile.Scheme.StartsWith("http"))
throw new ArgumentException("Input URI must represent a remote URL path", "existingFile");
// Do a WebRequest.Create call and attempt download... (Perhaps to MemoryStream for future use)
Hope that helps.
Andrew.

Related

OpenStreamForReadAsync fails with "The Parameter is Incorrect" from root

I'm trying to figure out the proper way to load resources that I have included in my package. There are a few other questions similar to this (e.g. Unable to access Asset files in Metro app), but I'd like to avoid having to manually construct arbitrary ms-appx:\\\ paths if possible.
// The location of everything in my package.
StorageFolder packageLocation = Package.Current.InstalledLocation;
// The folder I want to load a file from
StorageFolder resources = await packageLocation.GetFolderAsync("Resources");
// I can successfully find the file, and then open a stream.
StorageFile file = await resources.GetFileAsync("Default.xml");
Stream streamFromFile = await file.OpenStreamForReadAsync();
// Also, I can just directly open a stream for the file from the folder.
Stream streamFromFolder = await resources.OpenStreamForReadAsync("Default.xml");
// Error: The parameter is incorrect
Stream streamFromRoot = await packageLocation.OpenStreamForReadAsync("Resources/Default.xml")
I've tried many combinations including ./Resources/..., /Resources/..., ms-appx:///Resources/.... Why doesn't it work from the root folder?
Note: I haven't verified it yet, but I feel like I have the same issue with other 'root' folders such as ApplicationData.Current.LocalFolder.
Please test with the following syntax.
var file = await packageLocation.GetFileAsync(#"Resources\Default.xml");
or using stream
var stream = await packageLocation.OpenStreamForReadAsync(#"Resources\Default.xml");
As a follow up to the answer provided by Jean-Sebastien I wanted to point out a few other scenarios where slashes matter.
If you use the StorageFile.GetFileFromApplicationUriAsync API, this accepts a URI parameter which can be prefixed with ms-appx:///.
var uri = new Uri(#"ms-appx:///Resources\DefaultPickerView.xml");
var file1 = await StorageFile.GetFileFromApplicationUriAsync(uri);
Note that when you create the URI the back slashes are all converted into forward slashes.
On the other hand, I was unable to get StorageFile.GetFileFromPathAsync to work at all, regardless of what combination of prefixes and slashes I used. The GetFileFromPathAsync MSDN documentation however, does indicate that you can't use forward slashes in your path.

Application.GetResourceStream can't file the file in the Uri

I'm trying to access a .js file.
The file is located inside Database folder and named myfile.js which is just a JSON formatted text-file.
This is the code I'm using (this is run from MainPage.xaml.cs:
Uri uri = new Uri("/Database/myfile.js", UriKind.Relative);
var resource = Application.GetResourceStream(uri);
StreamReader streamReader = new StreamReader(resource.Stream);
string rawData = streamReader.ReadToEnd();
It always throw an exception of NullReferenceException because the resource variable is null.
So, the problem is in the Uri. I tried to use:
#"/Database/myfile.js"
"/Database/myfile.js"
"/LQI;component/Database/myfile.js"
But it doesn't work.
When I tried to move my file to root directory and replace the Uri string with
#"myfile.js"
it works! But I don't want that.
I also tried to rename the extension become .txt but nothing.
Please help.
Thanks!
Edit: I set the Build Action to "Content" which is default. I tried to set it to "Resource" but it doesn't work neither.
Edit #2: Okay, I found a clue (https://stackoverflow.com/a/12122332/2649132) that the LQI;component/Database/myfile.js only work when I set the item into Resource. And it does work.
But, the question will be still open since I doesn't work when I set the build action to "Content" with regular path.
The path is a relative path so take the leading "/" off of your path string so it reads "Database/myfile.js" and it should work fine.

How can I workaround Path too long exception in c# during WebClient.DownloadFile

I get an exception when I try to download file using webClient.DowloadFile.
WebClient webClient = new WebClient();
Uri downloadUri = new Uri("http://ia.mediaimdb.com/images/M/MV5BMjA5MTE1MjQyNV5BMl5BanBnXkFtZTcwODI4NDMwNw##._V1._SY0.jpg");
string posterFilePath =
"D:\Visual Studio Projects\Projects\TFS Source Control\" +
"MyMovieManager\MyMoviesManager\MyMoviesManager\bin\Debug\" +
"MoviesDB\Journey.2.The.Mysterious.Island.2012.DVDRip.XviD-DEPRiVED[ExtraTorrent]\" +
"Journey.2.The.Mysterious.Island.2012.DVDRip.XviD-DEPRiVED[ExtraTorrent].png";
webClient.DownloadFile(downloadUri, posterFilePath);
I found other cases that this exception was thrown and my solution was to use functions from kernel32 and write other functions that will replace the File and Path functions.
Is there something that I can do about DownloadFile function?
You could use the LongPathFile class from the BCL project, and write to the resulting stream manually. This will require using DownloadData instead of DownloadFile, and managing the file writing yourself.
you can use webclient.DownloadFile to a temp file, i.e. C:\Temp\myDownload.png , then move it to the path you want. you will need to check whether the c:\Temp folder exists. if not, create it.
One thing to notice is that this exception will also be raised if the address to the file (the first argument) is too long, if you use the version of the function that accepts 2 strings.
Naturally the solution is to convert it to a Uri using new Uri(address).

User Permissions issue

I am using Visual Studio C# to parse an XML document for a file location from a local search tool I am using. Specifically I am using c# to query if the user has access to certain files and hide those to which it does not have access. I seem to have files that should return access is true however because not all files are local (IE some are web files without proper names) it is not showing access to files it should be showing access to. The error right now is caused by a url using .aspx?i=573, is there a work around or am I going to have to just remove all of these files... =/
Edit: More info...
I am using right now....
foreach (XmlNode xn in nodeList)
{
string url = xn.InnerText;
//Label1.Text = url;
try
{ using (FileStream fs = File.OpenRead(url)) { }
}
catch { i++; Label2.Text = i.ToString(); Label1.Text = url; }
}
The issue is, when it attempts to open files like the ....aspx?i=573 it puts them in the catch stack. If I attempt to open the file however the file opens just fine. (IE I have read access but because of either the file type or the append of the '?=' in the file name it tosses it into the unreadable stack.
I want everything that is readable either via url or local access to display else it will catch the error files for me.
I'm not sure exactly what you are trying to do, but if you only want the path of a URI, you can easily drop the query string portion like this:
Uri baseUri = new Uri("http://www.domain.com/");
Uri myUri = new Uri(baseUri, "home/default.aspx?i=573");
Console.WriteLine(myUri.AbsolutePath); // ie "home/default.aspx"
You cannot have ? in file names in Windows, but they are valid in URIs (that is why IE can open it, but Windows cannot).
Alternatively, you could just replace the '?' with some other character if you are converting a URL to a filename.
In fact thinking about it now, you could just check to see if your "document" was a URI or not, and if it isn't then try to open the file on the file system. Sounds like you are trying to open any and everything that is supplied, but it wouldn't hurt to performs some checks on the data.
private static bool IsLocalPath(string p)
{
return new Uri(p).IsFile;
}
This is from Check if the path input is URL or Local File it looks like exactly what you are looking for.
FileStream reads and writes local files. "?" is not valid character for local file name.
It looks like you want to open local and remote files. If it is what you are trying to do you should use approapriate metod of downloading for each type - i.e. for HTTP you WebRequest or related classes.
Note: it would be much easier to answer if you'd say: when url is "..." File.OpenRead(url) failes with exception, mesasge "...".

What is wrong with this URI?

Hej
I am trying to load an (embedded) image in a wpf application, using an Uri but I keep getting an exception.
The code is:
new BitmapImage(new Uri("pack://application:,,,,/Icons/m.png"));
(In case it isn't clear, I am trying to load the m.png file from the Icons folder, which
has been marked as an embedded ressource).
and the exception is
NotSupportetException (the URI prefix is not recognized)
Can anybody tell me what the uri should have been?
Three commas must be instead of four in your string:
new BitmapImage(new Uri("pack://application:,,,/LibName;component/Icons/m.png"));
LibName - points to assembly where resource is hosted.
You may take a look at this blog post. The solution is to register a custom uri parser so that it recognizes the pack protocol:
UriParser.Register(
new GenericUriParser(GenericUriParserOptions.GenericAuthority), "pack", -1
);

Categories