Fájlok elérése relatív URI-vel hogyan?
2018-06-24T21:22:03+02:00
2018-07-16T13:56:03+02:00
2022-08-11T05:00:31+02:00
krisztian999tr
Sziasztok!
Van egy programom ami letölt képeket egy szerverről és generál magának közvetlen az exe fájlt tartalmazó elérési útra (ami ugye relatív) egy App Data  és azon belül egy itemThumbnails mappát. Ide tölti be a képeket. 

Amikor be akarom olvastatni vele a képekhez tartozó szöveget és a képek nevét, akkor hibátlanul olvassa a generált csv fájlt és tömbbe rendezi azt. 

string itemGroupDatabaseURL = "./App Data/itemCategorx_DB.dat"; StreamReader ItemGroupDataFile = new StreamReader(itemGroupDatabaseURL, Encoding.Default);
A képfájlok egyébként átnevezésre kerülnek, mindegyik az itemThumbnails  mappán belül az itemImg_ nevet kapja és utána egy számot ami növekvő, ha még nem létezik a fájl (például: itemImg_001.png). A program egyébként WPF app.

Próbáltam a képek elérését is hasonló módon, mint a CSV útvonalnál, de nem hajlandó a program megjeleníttetni, de még csak hibaüzenetet sem dob. 

// Create source BitmapImage myBitmapImage = new BitmapImage(); // BitmapImage.UriSource must be in a BeginInit/EndInit block myBitmapImage.BeginInit(); myBitmapImage.UriSource = new Uri(@"./App Data/itemThumbnails/" + imageURI, UriKind.Relative); //MessageBox.Show("Forrás: " + Convert.ToString(myBitmapImage.UriSource)); myBitmapImage.EndInit(); BitmapImage SetImage = myBitmapImage; GridItem1_image.Source = SetImage;
Mi lehet a baj?
Mutasd a teljes hozzászólást!
A problémát sikerült reprodukálni: tényleg elég zavarba ejtő, hogy a relatív URI nem működik.

Ennek okát még keresem, mert kíváncsi lettem, de addig is workaroundként egyszerűen alakítsd abszolúttá:

myBitmapImage.BeginInit(); string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"App Data\itemThumbnails", IMG_NAME); myBitmapImage.UriSource = new Uri(path); myBitmapImage.EndInit();

Olyasmire tippelek, hogy nem az a base url, amire az ember számítana.

Szerk.: ennyi időt tudtam rászánni. Ez valami bug lesz.

Itt egy másik konkrét példa relatív URI használatára: ennek működnie kéne, nekem nem megy.

Jómagam ebbe korábban nem futottam bele, mert mindig megbízhatóbbnak tartottam az általam kalkulált abszolút elérési utakat. Szerintem ez az ajánlott megközelítés.
Mutasd a teljes hozzászólást!

  • És a fájlok amúgy megjelennek a nevezett könyvtárakban és képnézővel meg is tudod őket nyitni?
    Mutasd a teljes hozzászólást!
  • Igen, az elérési úttal nincs baj és meg is jelennek a fájlok. Ezért nem igazán értem
    Mutasd a teljes hozzászólást!
  • Jól értem ugye, hogy a programod helyi gépen fut, így jogosultsági stb. problémák nem fordulhatnak elő?

    Kezdetnek próbáld betölteni a képet egyszerűbb alternatív módszerrel, hogy megbizonyosodj róla, biztosan minden stimmel I/O körül (beleértve, hogy a path valóban jó), pl. így:

    System.IO.File.ReadAllBytes()
    Mutasd a teljes hozzászólást!
  • A problémát sikerült reprodukálni: tényleg elég zavarba ejtő, hogy a relatív URI nem működik.

    Ennek okát még keresem, mert kíváncsi lettem, de addig is workaroundként egyszerűen alakítsd abszolúttá:

    myBitmapImage.BeginInit(); string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"App Data\itemThumbnails", IMG_NAME); myBitmapImage.UriSource = new Uri(path); myBitmapImage.EndInit();

    Olyasmire tippelek, hogy nem az a base url, amire az ember számítana.

    Szerk.: ennyi időt tudtam rászánni. Ez valami bug lesz.

    Itt egy másik konkrét példa relatív URI használatára: ennek működnie kéne, nekem nem megy.

    Jómagam ebbe korábban nem futottam bele, mert mindig megbízhatóbbnak tartottam az általam kalkulált abszolút elérési utakat. Szerintem ez az ajánlott megközelítés.
    Mutasd a teljes hozzászólást!
  • Készítettem hozzá még egy visszaellenőrzőt is és futás során mindig a "Van ilyen" üzenetet kaptam és a megfelelő elérési utat: 

    string ThumbnailRelativeUri = "./App Data/itemThumbnails/" + imageURI; if (File.Exists(ThumbnailRelativeUri)) { MessageBox.Show("Van ilyen: " + ThumbnailRelativeUri); } else { MessageBox.Show("Nincs ilyen: " + ThumbnailRelativeUri); }
    Mutasd a teljes hozzászólást!
  • Örök hála! Ezzel a megoldással működik. De ilyet én még nem tapasztaltam, hogy a System IO hibátlanul eléri  és kezeli a fájlt és egy elvileg ugyanazt az alap osztályt használó másik parancs nem, de még csak hibával se dob ki, mint az IO ha nem létezne a megadott elérés...

    WPF-nek mindig lesznek furcsaságai
    Mutasd a teljes hozzászólást!
  • Az URI nem csak fájlok elérési útjának meghatározására alkalmas, hanem gyakorlatilag bármilyen erőforráshoz használható, legyen az helyi gépen, interneten, vagy erőforrásban. Ahhoz, hogy egy komponens fel tudjon használni egy Uri objektumban tárolt elérési utat, tudnia kell, hogy milyen protokoll szerint keresse az erőforrást. A protokollt szintén az Uri objektum tárolja, és sokféle lehet, például: http, ftp, file, pack. Ha viszont megadod a protokollt, akkor már nem tudsz relatív útvonalat használni. Tehát a megoldás az, hogy abszolút elérési útvonalat kell használni.
    Mutasd a teljes hozzászólást!
  • Ha viszont megadod a protokollt, akkor már nem tudsz relatív útvonalat használni.

    Ez így nem igaz, pont, hogy az UriKind.Relative használatával relatív útvonalat is meg lehet adni, és a linkelt, 2014-es példakód szerint akkor ez még működött a helyi file-okon is. A leírás sehol nem ír limitációról.

    Részemről ezért valószínűsítem, hogy ez egy alacsony prioritású bug.
    Mutasd a teljes hozzászólást!
  • Melyik állításom nem igaz konkrétan?
    Mutasd a teljes hozzászólást!
  • Idéztem.
    Mutasd a teljes hozzászólást!
  • Mutasd meg kérlek, hogy lehet, vagy hogy kellene tudni protokoll megadásával relatív útvonalat megadni. Elegendő egy string literál.
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!
  • Ebben mi a protokoll?
    Mutasd a teljes hozzászólást!
  • Légy szíves, nézd meg a példát a linken, hadd ne másoljam ide!

    De eleve mellékvágányon vagyunk: erre sem kéne, hogy szükség legyen, a topicnyitó kolléga kódjának ettől még működnie kéne. Szerinted miért nem működik?
    Mutasd a teljes hozzászólást!
  • Protokoll (scheme) lehetnek például a következők: http, ftp, net, ws, gopher, file, pack, stb. Például a "http://www.microsoft.com/image.png" URL-ben a protokoll a "http". A kérésem arra irányult, hogy mutasd meg, hogyan lehetséges relatív útvonalat megadni, ha megadod a protokollt is. Tudomásom szerint nem lehet, de tévedhetek is. Szóval szerintem a protokoll mellett az authority információt is meg kell adni. Te pedig ezt az állításomat vontad kétségbe. Ezért lett volna jó, ha megmutatod, hogy lehet megoldani.

    Leírtam már, hogy szerintem miért nem működik. De akkor leírom más szavakkal is:
    A BitmapImage nem csak helyi számítógépről, hanem erőforrásból, az internetről, vagy más helyről is meg tud jeleníteni képet. Ennek módja, ha a forrást a BitmapSource tulajdonságán keresztül adjuk meg. Ahhoz, hogy be tudja azonosítani a konkrét helyet, szükséges, hogy az elérési utat kontextusba helyezzük. Jelen esetben nincs alapértelmezett kontextus, ezért a használni kívánt kontextust valamilyen módon jelezni kell azt az objektum számára. Ehhez definiálni kell a sémát is. Ha abszolút elérési út kerül megadásra, akkor tudni fogja, hogy hol keresse az erőforrást. Egy "./dir/file.png"-ről viszont nem lehet egyértelműen eldönteni, hogy hol, és milyen protokoll szerint kell keresni. És mivel meg kell adni a sémát, ezért abszolút útvonalat kell használni.
    Mutasd a teljes hozzászólást!
  • Ott a példa, idemásolom. Megadtuk a protokollt, és a relatív útvonalat is:

    Uri absoluteUri = new Uri("http://www.contoso.com/"); Uri relativeUri = new Uri("/catalog/shownew.htm?date=today", UriKind.Relative); Uri combinedUri = new Uri(absoluteUri, relativeUri);

    Abszolút URI használata nélkül, egy sorban nem megy, ebben igazad van. Ennél pedig egyszerűbb egyből az abszolút URI-t létrehozni.

    Ebben a példában azonban protokoll megadása nélkül használják a relatív URI-t. Ennek így elvileg működnie kéne.

    In the preceding code snippet, UriKind lets you specify if the image is relative to the application path or has an absolute path.

    Sajnos nem találtam kész solution-t, amit ki lehetne próbálni, és nekem nem működik a linkelt kód. Ezért jutottam arra, hogy ez szerintem bug, amit talán be sem jelentettek, mert ez a használati mód nem lehet túl gyakori.
    Mutasd a teljes hozzászólást!
  • Ezek szerint mégis igaz, amit írtam. 

    Mi az, amit ismerünk?
    - Van egy darab kód a weben, amiről nem tudjuk, hogy 2014-ben valóban működött-e
    - Jelenlegi körülmények között viszont nem működik
    - Más kódot eddig nem sikerült találni

    Én nem azt a következtetést vonnám le ebből, hogy működnie kellene.

    Barátság és világbéke. 
    Mutasd a teljes hozzászólást!
  • A saját hozzászólásomhoz egy kis kiegészítés:
    A BitmapImage valóban nem rendelkezik alapértelmezett kontextussal, azonban az Image igen, és a kontextus erőforráshasználatot feltételez. Ime a példa:

    Ez a kódsor:

    RelativeImage.Source = new BitmapImage(new Uri(@"./App Data/itemThumbnails/test.jpg", UriKind.Relative));
    Ezt az URI-t eredményezi:

    pack://application:,,,/BitmapImageUri;component/App Data/itemThumbnails/test.jpg
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd