49 votes

Conversion d'un chemin d'accès URI en un chemin d'accès relatif au système de fichiers en .NET

Comment convertir un chemin d'accès URI absolu ou relatif (par ex. /foo/bar.txt ) vers un chemin d'accès relatif au système de fichiers (par segment) correspondant (par ex. foo\bar.txt ) dans .NET ?

Mon programme n'est pas une application ASP.NET.

0 votes

Il aurait peut-être été plus logique pour moi d'utiliser un chemin d'accès URI relatif comme exemple.

80voto

Ashish Gupta Points 5229

Avez-vous déjà essayé Server.MapPath ?
ou Uri.LocalPath propriété ? Quelque chose comme le suivant :

string uriString = "file://server/filename.ext";
// Lesson learnt - always check for a valid URI
if(Uri.IsWellFormedUriString(uriString))
{
    Uri uri = new Uri(uriString);
    Console.WriteLine(uri.LocalPath);
}

0 votes

@Binaire, @Gareth, je suis heureux que cela vous ait aidé.

7 votes

Eh bien, j'ai dû modifier ce code pour utiliser ce fragment à la place Console.WriteLine(uri.LocalPath + Uri.UnescapeDataString(uri.Fragment)) ceci est dû au caractère # dans les noms de fichiers

11voto

acdx Points 317

J'ai trouvé un moyen de produire un chemin absolu complet du système de fichiers à partir d'un URI relatif ou absolu et d'un chemin de base.

Avec :

Uri basePathUri = new Uri(@"C:\abc\");

À partir d'un URI relatif :

string filePath = new Uri(basePathUri, relativeUri).AbsolutePath;

À partir d'un URI absolu :

// baseUri is a URI used to derive a relative URI
Uri relativeUri = baseUri.MakeRelativeUri(absoluteUri);
string filePath = new Uri(basePathUri, relativeUri).AbsolutePath;

5voto

Nick Craver Points 313913

Vous pouvez le faire :

var localPath = Server.MapPath("/foo/bar.txt");

Voir MSDN pour plus de détails

2 votes

Mon programme n'est pas une application ASP.NET, comment puis-je avoir accès à l'objet Serveur ?

0 votes

@acdx - Je suis confus alors... par rapport à quoi, une application en cours d'exécution ? Votre question est étiquetée uri donc je suis confus si ce n'est pas du web, expliquez ?

0 votes

J'aimerais obtenir un chemin de fichier relatif, tel que foo\bar.txt que je peux passer à Path.Combine pour créer un chemin de fichier absolu.

3voto

dcp Points 26928

Vérifiez Server.MapPath . http://msdn.microsoft.com/en-us/library/ms524632.aspx

S'il ne s'agit pas d'une application ASP.NET, consultez :

System.IO.Path.GetFullPath("filename")

0voto

Tout le monde n'a pas accès à server.MapPath en raison de changements de backend ou de framework, et il existe de nombreuses façons de le faire, l'une d'entre elles pouvant être la suivante

public enum FileLocation
{
    NotSet,
    Disk,
    Resource,
}

private static readonly string[] FileExtenstions = new[] {
    ".js"
    ,".ts"
    ,".vue"
    ,".css"
    ,".jpg"
    ,".png"
    ,".gif"
    ,".ico"
    ,".svg"
    ,".ttf"
    ,".eot"
    ,".ttf"
    ,".woff"
    ,".woff2"
    ,".mp4"
    ,".mp3"
    ,".emf"
};

public FileLocation IsMappedTo(Uri uri)
{
    if (uri is null)
    {
        throw new ArgumentNullException(nameof(uri));
    }
    //make sure we support .net default URI contract
    if (uri.IsFile)
        return FileLocation.Disk;

    //now assume you are looking in a web application
    var path = uri.AbsolutePath;
    if (path.Length == 0 || path.Equals("/",StringComparison.Ordinal) || path.Length< FileExtenstions.Min(s=>s.Length))
        return FileLocation.NotSet;

    //get the directory normally one would use IWebHostEnvironment.ContentRootPath different versions .net will have other methods
    var dir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");

    //get all resources names from the assembly hosting this class out side if the loop from this assembly you can also use
    //you can also use GetManifestResourceNames() to use the web application's assembly
    var resourceNames = new HashSet<string>(this.GetType().Assembly.GetManifestResourceNames());
    var entryAssembly = Assembly.GetEntryAssembly();
    if (entryAssembly != null && entryAssembly != this.GetType().Assembly)
    {
        foreach (var entry in entryAssembly.GetManifestResourceNames())
        {
            if (string.IsNullOrEmpty(entry))
                resourceNames.Add(entry);
        }
    }

    for (var i = 0; i < FileExtenstions.Length; i++)
    {
        if (FileExtenstions[i].Equals(path[FileExtenstions[i].Length..], StringComparison.OrdinalIgnoreCase) || path.Contains(FileExtenstions[i], StringComparison.OrdinalIgnoreCase))
        {
            //exists on disk
            if (File.Exists(Path.Combine(dir, path.Replace("/", @"\", StringComparison.Ordinal))))
                return FileLocation.Disk;

            //has a file as an embedded resource with the same name (ignores the path) so you might have duplicates names
            if (resourceNames.Any(a => a.EndsWith(path.Split('/')[^1], StringComparison.OrdinalIgnoreCase)))
                return FileLocation.Resource;
        }
    }

    return FileLocation.NotSet;
}

après ça, tu fais tout simplement :

switch (IsMappedTo(url))
{
    case FileLocation.NotSet:
        break;

    case FileLocation.Disk:
        break;

    case FileLocation.Resource:

        break;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X