파일 경로를 파일 URI로 변환 하시겠습니까?
.NET Framework에 경로 (예 "C:\whatever.txt"
:)를 파일 URI (예 :)로 변환하는 방법이 "file:///C:/whatever.txt"
있습니까?
선택 System.Uri의 클래스는 (절대 경로에 파일 URI)에서 반대가 있지만 아무것도까지 내가 파일 URI로 변환 찾을 수있다.
또한 이것은 ASP.NET 응용 프로그램 이 아닙니다 .
System.Uri
생성자는 전체 파일 경로를 분석하고 URI 스타일의 경로로를 설정하는 기능이 있습니다. 따라서 다음을 수행 할 수 있습니다.
var uri = new System.Uri("c:\\foo");
var converted = uri.AbsoluteUri;
아무도 알지 못하는 것은 어떤 System.Uri
생성자도 특정 경로를 백분율 기호로 올바르게 처리 하지 못한다는 것입니다.
new Uri(@"C:\%51.txt").AbsoluteUri;
"file:///C:/Q.txt"
대신에 당신에게 제공합니다 "file:///C:/%2551.txt"
.
더 이상 사용되지 않는 dontEscape 인수의 값은 차이가 없으며 UriKind를 지정해도 같은 결과가 나타납니다. UriBuilder로 시도해도 도움이되지 않습니다.
new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri
이것도 돌아옵니다 "file:///C:/Q.txt"
.
내가 알 수있는 한 프레임 워크에는 실제로 올바르게 수행 할 수있는 방법이 없습니다.
우리는 슬래시와 함께 백 슬래시를 대체하여 그것을 시도하고 경로를 급지 할 수 있습니다 Uri.EscapeUriString
- 즉
new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri
이것은 처음에 작동하는 것 같다,하지만 당신은 그것을 경로를 주면 C:\a b.txt
당신은 끝낼 file:///C:/a%2520b.txt
대신 file:///C:/a%20b.txt
- 어떻게 든 것을 결정 어떤 순서가 다른 사람을 디코딩하지만해야합니다. 이제 우리는 접두사를 "file:///"
붙일 수는 있지만 이것은 UNC 경로 \\remote\share\foo.txt
를 고려 하지 못합니다 . Windows에서 일반적으로 받아 들여지는 것처럼 보이는 것은 url을 형식의 의사 URL로 바꾸는 file://remote/share/foo.txt
것이므로 우리도 고려해야합니다.
EscapeUriString
또한 '#'
캐릭터를 탈출하지 못한다는 문제가 있습니다 . 이 시점에서 우리는 다른 선택의 여지가 없지만 처음부터 우리 자신의 방법을 만드는 것 같습니다. 이것이 내가 제안하는 것입니다.
public static string FilePathToFileUrl(string filePath)
{
StringBuilder uri = new StringBuilder();
foreach (char v in filePath)
{
if ((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '9') ||
v == '+' || v == '/' || v == ':' || v == '.' || v == '-' || v == '_' || v == '~' ||
v > '\xFF')
{
uri.Append(v);
}
else if (v == Path.DirectorySeparatorChar || v == Path.AltDirectorySeparatorChar)
{
uri.Append('/');
}
else
{
uri.Append(String.Format("%{0:X2}", (int)v));
}
}
if (uri.Length >= 2 && uri[0] == '/' && uri[1] == '/') // UNC path
uri.Insert(0, "file:");
else
uri.Insert(0, "file:///");
return uri.ToString();
}
이것은 일반적으로 Windows에서 수행되는 방식 인 것처럼 + 및 : 인코딩되지 않은 채로 둡니다. Internet Explorer가 인코딩 된 파일 URL의 유니 코드 문자를 이해할 수 없으므로 latin1 만 인코딩합니다.
VB.NET :
Dim URI As New Uri("D:\Development\~AppFolder\Att\1.gif")
다른 출력 :
URI.AbsolutePath -> D:/Development/~AppFolder/Att/1.gif
URI.AbsoluteUri -> file:///D:/Development/~AppFolder/Att/1.gif
URI.OriginalString -> D:\Development\~AppFolder\Att\1.gif
URI.ToString -> file:///D:/Development/~AppFolder/Att/1.gif
URI.LocalPath -> D:\Development\~AppFolder\Att\1.gif
짧막 한 농담:
New Uri("D:\Development\~AppFolder\Att\1.gif").AbsoluteUri
출력 :
file:///D:/Development/~AppFolder/Att/1.gif
위의 솔루션은 Linux에서 작동하지 않습니다.
.NET Core를 사용하여 실행하려고 new Uri("/home/foo/README.md")
하면 예외가 발생합니다.
Unhandled Exception: System.UriFormatException: Invalid URI: The format of the URI could not be determined.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
...
CLR에 어떤 종류의 URL이 있는지에 대한 힌트를 제공해야합니다.
이것은 작동합니다 :
Uri fileUri = new Uri(new Uri("file://"), "home/foo/README.md");
...에 의해 반환되는 문자열 fileUri.ToString()
은"file:///home/foo/README.md"
이것은 Windows에서도 작동합니다.
new Uri(new Uri("file://"), @"C:\Users\foo\README.md").ToString()
... 방출 "file:///C:/Users/foo/README.md"
.NET 4.5 이상에서는 다음을 수행 할 수도 있습니다.
var uri = new System.Uri("C:\\foo", UriKind.Absolute);
구조에 UrlCreateFromPath ! 확장 및 UNC 경로 형식을 지원하지 않으므로 완전히 극복 할 수는 없지만 극복하기는 어렵지 않습니다.
public static Uri FileUrlFromPath(string path)
{
const string prefix = @"\\";
const string extended = @"\\?\";
const string extendedUnc = @"\\?\UNC\";
const string device = @"\\.\";
const StringComparison comp = StringComparison.Ordinal;
if(path.StartsWith(extendedUnc, comp))
{
path = prefix+path.Substring(extendedUnc.Length);
}else if(path.StartsWith(extended, comp))
{
path = prefix+path.Substring(extended.Length);
}else if(path.StartsWith(device, comp))
{
path = prefix+path.Substring(device.Length);
}
int len = 1;
var buffer = new StringBuilder(len);
int result = UrlCreateFromPath(path, buffer, ref len, 0);
if(len == 1) Marshal.ThrowExceptionForHR(result);
buffer.EnsureCapacity(len);
result = UrlCreateFromPath(path, buffer, ref len, 0);
if(result == 1) throw new ArgumentException("Argument is not a valid path.", "path");
Marshal.ThrowExceptionForHR(result);
return new Uri(buffer.ToString());
}
[DllImport("shlwapi.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int UrlCreateFromPath(string path, StringBuilder url, ref int urlLength, int reserved);
In case the path starts with with a special prefix, it gets removed. Although the documentation doesn't mention it, the function outputs the length of the URL even if the buffer is smaller, so I first obtain the length and then allocate the buffer.
Some very interesting observation I had is that while "\\device\path" is correctly transformed to "file://device/path", specifically "\\localhost\path" is transformed to just "file:///path".
The WinApi function managed to encode special characters, but leaves Unicode-specific characters unencoded, unlike the Uri construtor. In that case, AbsoluteUri contains the properly encoded URL, while OriginalString can be used to retain the Unicode characters.
The workaround is simple. Just use the Uri().ToString() method and percent-encode white-spaces, if any, afterwards.
string path = new Uri("C:\my exampleㄓ.txt").ToString().Replace(" ", "%20");
properly returns file:///C:/my%20exampleㄓ.txt
참고URL : https://stackoverflow.com/questions/1546419/convert-file-path-to-a-file-uri
'development' 카테고리의 다른 글
Rails 애플리케이션을 프로덕션으로 변경 (0) | 2020.05.14 |
---|---|
DecimalFormat의 소수점 구분 기호를 쉼표에서 점 / 점으로 변경하는 방법은 무엇입니까? (0) | 2020.05.13 |
Cloud Firestore와 Firebase 실시간 데이터베이스의 차이점은 무엇입니까? (0) | 2020.05.13 |
배치 파일에서 명령 출력을 변수로 설정하는 방법 (0) | 2020.05.13 |
npm을 사용하여 모듈을 전체적으로 설치하려면 어떻게합니까? (0) | 2020.05.13 |