从Google Drive下载文件到字节数组失败 – C# HttpClient

huangapple go评论57阅读模式
英文:

File download from Google Drive to byte array failing - C# HttpClient

问题

以下是翻译好的代码部分:

public static async Task<byte[]> ReadWebFileBinaryAsync(HttpClient httpClient, string webUrl)
{
    byte[] bytes;

    try
    {
        HttpResponseMessage response = await httpClient.GetAsync(webUrl);
        response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (Stream stream = await response.Content.ReadAsStreamAsync())
            {
                stream.CopyTo(memoryStream);
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            bytes = memoryStream.ToArray();
        }

        return bytes;
    }
    catch (Exception ex)
    {
        // ...
    }
}
httpClientHandler = new HttpClientHandler
{
    AllowAutoRedirect = true,            // Allegedly the default, but to make sure
    MaxAutomaticRedirections = 20
};

httpClient = new HttpClient(httpClientHandler);
httpClient.Timeout = TimeSpan.FromSeconds(60);

// Accept all languages
httpClient.DefaultRequestHeaders.AcceptLanguage.Clear();
httpClient.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("*"));

// Accept binary data
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/octet-stream"));

请注意,代码中的引号已经被恢复,但是翻译部分仅包括代码本身,不包括注释或其他内容。

英文:

I'm new to HttpClient. The following code to download a binary file returns a byte array of the wrong length and containing the wrong data:

public static async Task&lt;byte []&gt; ReadWebFileBinaryAsync ( HttpClient httpClient, string webUrl )
{
	byte [] bytes;

	try
	{
		HttpResponseMessage response = await httpClient.GetAsync ( webUrl );
		response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue( &quot;application/octet-stream&quot; );
		using ( MemoryStream memoryStream = new MemoryStream () )
		{
			using ( Stream stream = await response.Content.ReadAsStreamAsync () )
			{
				stream.CopyTo ( memoryStream );
			}
			memoryStream.Seek ( 0, SeekOrigin.Begin );
			bytes = memoryStream.ToArray ();
		}

		return bytes;
	}
	catch ( Exception ex )
	{
        // ...
	}
}

httpClient is initialised app-wide as follows:

httpClientHandler = new HttpClientHandler
{
	AllowAutoRedirect = true,			// Allegedly the default, but to make sure
	MaxAutomaticRedirections = 20
};

httpClient = new HttpClient ( httpClientHandler );
httpClient.Timeout = TimeSpan.FromSeconds ( 60 );

// Accept all languages
httpClient.DefaultRequestHeaders.AcceptLanguage.Clear();
httpClient.DefaultRequestHeaders.AcceptLanguage.Add ( new System.Net.Http.Headers.StringWithQualityHeaderValue ( &quot;*&quot; ) );

// Accept binary data
httpClient.DefaultRequestHeaders.Accept.Add ( new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue ( &quot;application/octet-stream&quot; ) );

The web file is 688kb and has a public url of the form

https://drive.google.com/file/d/xxxxx/view?usp=share_link

Anyone who has the link can open it in a web browser.

The returned array contains only 75K bytes, and as mentioned the data is completely wrong (comparing with the web file in a hex editor). Another file of size just 14KB likewise returns an array of 75K bytes! The exact number of bytes varies slightly each time the app is run, but between 75,400 and 75,600.

This is in .NET 7.0.1, Xamarin.Forms.

I don't know if my code is wrong or there is something funny about downloading from Google Drive. Maybe the Google API must be used? A way to transform the url maybe? The files I care about will be less than 1MB. Any help appreciated!

答案1

得分: 0

Google Drive链接会在页面上插入一个下载按钮,导致上面的代码失败。

通过首先调用以下方法来解决这个问题,该方法适用于大小约为25MB的文件。较大的文件可能需要使用Google API解决方案。

private string CheckForGoogleDriveUrl(string url)
// 如果给定的url是Google Drive url,则返回等效的直接url,避免初始带有下载按钮的页面
// 将 https://drive.google.com/file/d/xxxxx/view?usp=share_link 转换为 https://drive.google.com/uc?export=download&amp;id=xxxxx
// 注意:对于Google认为需要进行病毒检查的文件,大约为25MB,此方法可能不起作用,因为Google会发出提示
{
    if (url.Contains("https://drive.google.com/file"))
    {
        string[] s = url.Split('/');
        url = s[5];
        s = url.Split('/');
        url = "https://drive.google.com/uc?export=download&amp;id=" + s[0];
    }

    return url;
}
英文:

For Google Drive links, Google interposes a page with a Download button, causing the code above to fail.

The problem is solved by first calling the following method, which works for files up to around 25Mb in size. Larger files would probably require a Google API solution.

private string CheckForGoogleDriveUrl ( string url )
// If given url is a Google Drive url, returns an equivalent direct url, avoiding initial page with download button
// Transforms https://drive.google.com/file/d/xxxxx/view?usp=share_link to https://drive.google.com/uc?export=download&amp;id=xxxxx
// Note: Probably does not work for files that Google considers too large to virus check, around 25MB, as Google will issue a prompt
{
	if ( url.Contains ( &quot;https://drive.google.com/file&quot; ) )
	{
		string [] s = url.Split ( &#39;/&#39; );
		url = s [5];
		s = url.Split ( &#39;/&#39; );
		url = &quot;https://drive.google.com/uc?export=download&amp;id=&quot; + s [0];
	}

	return url;
}

huangapple
  • 本文由 发表于 2023年6月11日 20:38:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450513.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定