1

私は自分の問題に対する実用的な答えを見つけることができないようで、そこにいる誰かが助けてくれるのだろうかと思います。基本的に、私のWebサイトには、zipファイルをダウンロードするためのリンクがあります。

http://***.com/download.php?id=1

Webページでこのリンクをアクティブにすると、[名前を付けて保存]ダイアログが表示され、デフォルトの名前でファイルを保存できます。ThisIsMyZipFile.zip

私の問題は、c#を使用するnew Uri("http://***.com/download.pgp?id=1").IsFileと返されるため、を実行して最初の2バイトがであるかどうかを確認しfalseないと、これがファイルであることを検出できないように見えることです。webclient DownloadStringPK

また、文字列として手動でダウンロードしてヘッダーを検出し、ファイルを保存しても、同じファイル名を使用したいので、この例PKのデフォルトのファイル名としてWebサイトが使用したいものを見つけることができません。ThisIsMyZipFile.zip

誰かがこれらの2つの問題を解決する良い方法を知っていますか?

アップデート

Paulと彼の答えのおかげで、私は必要なことを正確に実行する次の関数を作成しました。

/// <summary>
/// Returns the responded HTTP headers of the given URL and if the link refers to the file it returns extra information about it.
/// </summary>
/// <param name="Url">The address.</param>
/// <returns>
/// null if a WebException is thrown
/// otherwise:
/// List of headers:
///     Keep-Alive          - Timeout value (i.e. timeout=2, max=100)
///     Connection          - The type of connection (i.e. Keep-Alive)
///     Transfer-Encoding   - The type of encoding used for the transfer (i.e. chunked)
///     Content-Type        - The type of Content that will be transferred (i.e. application/zip)
///     Date                - The servers date and time
///     Server              - The server that is handling the request (i.e. Apache)
///     AbsoluteUri         - The full Uri of the resulting link that will be followed.
/// The following key will be present if the link refers to a file
///     Filename            - The filename (not path) of the file that will be downloaded if the link if followed.
/// </returns>
public Dictionary<string, string> GetHTTPResponseHeaders(string Url)
{
    WebRequest WebRequestObject = HttpWebRequest.Create(Url);
    WebResponse ResponseObject = null;
    try
    {
        ResponseObject = WebRequestObject.GetResponse();
    }
    catch(WebException ex)
    {
        return null;
    }
    // Add the header inforamtion to the resulting list
    Dictionary<string, string> HeaderList = new Dictionary<string, string>();
    foreach (string HeaderKey in ResponseObject.Headers)
        HeaderList.Add(HeaderKey, ResponseObject.Headers[HeaderKey]);

    // Add the resolved Uri to the resulting list
    HeaderList.Add("AbsoluteUri", ResponseObject.ResponseUri.AbsoluteUri);

    // If this is a zip file then add the download filename specified by the server to the resulting list
    if (ResponseObject.ContentType.ToLower() == "application/zip")
    {
        HeaderList.Add("Filename", ResponseObject.ResponseUri.Segments[ResponseObject.ResponseUri.Segments.Length-1]);
    }

    // We are now finished with our response object
    ResponseObject.Close();

    // Return the resulting list
    return HeaderList;
}

4

2 に答える 2

2

Uri.IsFileURI に対して静的チェックを実行します。つまり、'scheme' 部分 (コロンを含む最初のビット) がfile:. URI に存在するリソースを要求することによって返される実際のコンテンツは調べません。(実際には、実際にはサーバーへの接続をまったく試行しないため、URI は実際には欠落しているリソースを指している可能性がありますが、IsFileそれでも機能します。)

リソースのコンテンツが特定のタイプであるかどうかを確認したい場合は、次のいずれかを行う必要があります。

  1. リソースの HTTP ヘッダーを取得します (それが HTTP または HTTPS リソースの場合: つまり、「スキーム」がhttpまたはの場合https)。
  2. リソース (少なくともその一部) を取得して調べます。

現在 2 を実行していますが、HTTP リソース (HTTP URL を使用) の場合は、1 を実行する方がクリーンで安価です。これは、HTTP リクエストを実行することで実行できます(または、&c.HEADとは対照的に)。これは、リソース自体を返さずに HTTP ヘッダーを返します。コードは次のようになります。GETPOST

var request = WebRequest.Create("http://somewhere.overtherainbow.com/?a=b");
request.Method = "HEAD";
WebResponse response = request.GetResponse();
//TODO check status code
string contentType = response.ContentType;
response.Close();

コンテンツ タイプはファイル タイプを示しますが、多くのバイナリ ファイルはオクテット ストリームとして返されるだけなので、異なるバイナリを区別したい場合は、リソース自体のマジック バイトを取得して調べる必要があるかもしれません。ファイルタイプ。(ただし、コンテンツ タイプは、バイナリ ファイルと Web ページを区別するのに十分なはずです。)

したがって、完全な解決策は次のようになります。

  1. GETリソースのリクエストを送信します。
  2. 応答ステータスをチェックして、エラーがないことを確認します。
  3. コンテンツ タイプ ヘッダーをチェックして、バイナリ オクテット ストリームがあるかどうかを確認します。
  4. 応答ストリームから 2 バイトを読み取って、ファイルが「PK」で始まるかどうかを確認します。
于 2012-12-27T11:19:23.430 に答える
1

実際にこの URL に HTTP リクエストを送信しない限り、特定の URL が原因でファイルがダウンロードされることを検出することは絶対にできません。

次に、2 番目の問題に進みます。HTTP リクエストを送信してファイルをダウンロードし、ファイル名を含む Content-Disposition ヘッダーを調べることができます。

using (var client = new WebClient())
{
    using (var stream = client.OpenRead("http://*.com/download.php?id=1"))
    {
        var disposition = client.ResponseHeaders["Content-Disposition"];
        if (disposition != null)
        {
            var cd = new ContentDisposition(disposition);
            if (!cd.Inline && !string.IsNullOrEmpty(cd.FileName))
            {
                using (var outputStream = File.OpenWrite(cd.FileName))
                {
                    stream.CopyTo(outputStream);
                }
            }
        }
        else
        {
            // The web server didn't send a Content-Disposition response header
            // so we have absolutely no means of determining the filename
            // you will have to use some default value here if you want to store it
        }
    }
}
于 2012-12-27T11:26:04.537 に答える