【问题标题】:File downloads failing on AndroidAndroid 上的文件下载失败
【发布时间】:2016-02-14 11:23:59
【问题描述】:

我需要允许用户从我们的服务器下载文件,并且我想通过 ASP.NET MVC 5 控制器操作来提供这些文件。我的操作如下所示:

public FileContentResult Download(int fileId)
{
    var myContent = GetContentForFile(fileId);
    var myFileMeta = GetFileMeta(fileId);

    if (myContent == null || myFileMeta == null)
        throw new FriendlyException("The file or its associated data could not be found.");

    return File(myContent.Content, myContent.MediaType, myFileMeta.FileName);
}

上面的内容很简单,它在 PC 和 iPhone 上运行良好,但在 Android 上却不行。使用 Fiddler,当我尝试下载我的一个文件时,我可以看到以下响应标头 - 在本例中是一个名为“1447114384146-643143584.jpg”的 JPG 文件:

HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: image/jpeg
Server: Microsoft-IIS/8.5
X-AspNetMvc-Version: 5.2
Content-Disposition: attachment; filename=1447114384146-643143584.jpg
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 12 Nov 2015 23:09:00 GMT
Content-Length: 1682868

请注意,我没有任何可靠的方法可以知道正确的 MIME 类型 - 这是一个问题吗?它能否解释为什么文件没有在 Android 中下载?

澄清一下,当我尝试使用 Android 从数据库中下载任何文件时,我会收到一个 toast 通知,告诉我“下载已开始”,但随后下载会在队列中等待一段时间为 0%,然后最终更改为“失败”。

我的尝试

我尝试了人们在类似问题中提出的各种建议,其中大部分与 content-disposition 标头或 content-type 标头有关。我尝试将每个文件的content-type 标头强制为application/octet-stream,我尝试为特定文件发送正确的content-type 标头。我尝试手动发送 content-disposition 标头。我尝试将文件扩展名强制为大写。

以上都没有奏效,事实上它们都没有对问题产生任何影响,无论好坏。我很惊讶这太难了——我觉得我一定错过了一些明显的东西?

其他信息

  • 浏览器:Android 上最新的 Chrome
  • 操作系统:Android 5.1(也适用于使用 Android 手机的同事,该手机是早期的 Android 版本(不确定具体是哪个版本),所以我认为这与特定的 Android 版本无关)。

更新

阅读此博客条目后:http://www.digiblog.de/2011/04/android-and-the-download-file-headers/ 我尝试按照建议设置标题,完全按照建议进行设置:

HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: application/octet-stream
Server: Microsoft-IIS/8.5
X-AspNetMvc-Version: 5.2
Content-Disposition: attachment; filename="1447114384146-643143584.JPG"
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 12 Nov 2015 23:42:18 GMT
Content-Length: 1682868

同样,这对问题没有任何影响。

进一步更新

我已经能够在 Marshmallow (Android v6.0) 设备上进行测试,并且下载工作正常。这似乎是棉花糖之前的问题。

【问题讨论】:

  • 一会儿,var?,它是 Android,它基于 Java,没有 JavaScript
  • 如标签所示,我正在 ASP.NET MVC 5 中开发它。(C#)(在问题中对此进行了一些澄清,因为我可以看到它的措辞令人困惑)。
  • 发布下载文件的代码。
  • @BNK 我不确定你的意思 - 通过访问 URL 下载文件。您可以通过单击链接在网站中执行此操作,但您也可以使用浏览器直接浏览到文件。

标签: c# android asp.net-mvc-5


【解决方案1】:

很遗憾,这是由于我的环境非常特殊的原因造成的,但我想在这里给出答案,以防其他人偶然发现同样的问题。

事实证明,Android 下载管理器不喜欢域名中的下划线,而我们的本地域名地址中包含下划线。我改用服务器的 IP 地址,一切正常。

例如:http://www.my_domain.com.au/file.png 将不起作用。这:http://192.168.x.x/file.png 确实有效。

作为这个问题的答案找到:Trouble downloading file from browser on Android

【讨论】:

    【解决方案2】:

    免责声明:我没有足够的代表添加到 cmets,所以我不得不在这里发表评论。

    1. 您是否使用模拟器尝试过不同版本的 Android 或 您是否只尝试过使用实际设备?
    2. 如果仅在设备上,代码是在生产中还是正在使用 通过本地无线连接到本地开发系统 连接?
    3. 您是否尝试过在设备上使用 Chrome 远程调试? https://developers.google.com/web/tools/chrome-devtools/debug/remote-debugging/remote-debugging?hl=en

    排除设备上设置问题的一种方法是使用 Xamarin + RestSharp 编写一个小型 Android 应用程序,该应用程序什么都不做,只是点击您的下载 URL 以查看是否有效。如果确实如此,那么这有助于将矛头指向 Chrome 本身。如果没有,那么至少您可以运行带有调试器的应用程序,以便更好地了解另一端发生的情况。

    https://xamarin.com/

    https://github.com/restsharp/RestSharp

    更新: Fiddler 在调用本地机器提供的测试时看到的响应标头

    HTTP/1.1 200 OK
    Cache-Control: private
    Content-Type: application/octet-stream
    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    Content-Disposition: attachment; filename=profile.jpg
    Date: Fri, 13 Nov 2015 02:09:23 GMT
    Content-Length: 218143
    

    更新:这是传入的请求服务器变量

    ALL_HTTP=HTTP_CACHE_CONTROL:max-age=0
    HTTP_CONNECTION:keep-alive
    HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    HTTP_ACCEPT_ENCODING:gzip, deflate, sdch
    HTTP_ACCEPT_LANGUAGE:en-US,en;q=0.8
    HTTP_COOKIE:_ga=GA1.1.420021277.1447377172
    HTTP_HOST:192.168.1.2
    HTTP_USER_AGENT:Mozilla/5.0 (Linux; Android 5.0.2; HTC One Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
    HTTP_UPGRADE_INSECURE_REQUESTS:1
    HTTP_DNT:1
    ALL_RAW=Cache-Control: max-age=0
    Connection: keep-alive
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: en-US,en;q=0.8
    Cookie: _ga=GA1.1.420021277.1447377172
    Host: 192.168.1.2
    User-Agent: Mozilla/5.0 (Linux; Android 5.0.2; HTC One Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
    Upgrade-Insecure-Requests: 1
    DNT: 1
    APPL_MD_PATH=/LM/W3SVC/2/ROOT
    APPL_PHYSICAL_PATH=C:\development\rumble-strip\projects\net-framework\RumbleStrip.Website\
    AUTH_TYPE=
    AUTH_USER=
    AUTH_PASSWORD=
    LOGON_USER=
    REMOTE_USER=
    CERT_COOKIE=
    CERT_FLAGS=
    CERT_ISSUER=
    CERT_KEYSIZE=
    CERT_SECRETKEYSIZE=
    CERT_SERIALNUMBER=
    CERT_SERVER_ISSUER=
    CERT_SERVER_SUBJECT=
    CERT_SUBJECT=
    CONTENT_LENGTH=0
    CONTENT_TYPE=
    GATEWAY_INTERFACE=CGI/1.1
    HTTPS=off
    HTTPS_KEYSIZE=
    HTTPS_SECRETKEYSIZE=
    HTTPS_SERVER_ISSUER=
    HTTPS_SERVER_SUBJECT=
    INSTANCE_ID=2
    INSTANCE_META_PATH=/LM/W3SVC/2
    LOCAL_ADDR=192.168.1.2
    PATH_INFO=/
    PATH_TRANSLATED=C:\development\rumble-strip\projects\net-framework\RumbleStrip.Website
    QUERY_STRING=&REMOTE_ADDR=192.168.1.5&REMOTE_HOST=192.168.1.5
    REMOTE_PORT=54748
    REQUEST_METHOD=GET
    SCRIPT_NAME=/
    SERVER_NAME=192.168.1.2
    SERVER_PORT=80
    SERVER_PORT_SECURE=0
    SERVER_PROTOCOL=HTTP/1.1
    SERVER_SOFTWARE=Microsoft-IIS/10.0
    URL=/
    HTTP_CACHE_CONTROL=max-age=0
    HTTP_CONNECTION=keep-alive
    HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    HTTP_ACCEPT_ENCODING=gzip, deflate, sdch
    HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.8
    HTTP_COOKIE=_ga=GA1.1.420021277.1447377172
    HTTP_HOST=192.168.1.2
    HTTP_USER_AGENT=Mozilla/5.0 (Linux; Android 5.0.2; HTC One Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
    HTTP_UPGRADE_INSECURE_REQUESTS=1
    HTTP_DNT=1
    IS_LOGIN_PAGE=1
    

    【讨论】:

    • 1.我已经在实际设备上进行了尝试(现在有 3 个不同的 Android 版本,5.1、6.0 和未知,但早于 5.0)。值得注意的是 Marshmallow 有效(添加到 OP)。 2. 代码部署在本地网络的服务器上。 3. 我没有,我可以试一试,但我认为这不太可能有帮助,因为问题似乎与收到的响应有关,而不是与发送的请求有关。
    • 我在本地机器上使用我的 Android 设备 (5.0.2) 通过无线使用 Chrome (46.0.2490.76) 进行了尝试。我能够从那里将文件下载到我的设备上。这是我使用的 MVC 控制器方法:public FileContentResult Index() { return File(System.IO.File.ReadAllBytes(@"c:\temp\profile.jpg"), "application/octet-stream", "profile.jpg"); }
    • 你能发布你的回复的标题吗?
    • 更新了答案,使响应格式更清晰。
    • 谢谢,遗憾的是我可以重现相同的响应,但仍然没有下载任何内容。哦,好吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 2012-04-15
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    相关资源
    最近更新 更多