使用 DownloadManager 从 S3 下载 apk 文件

Posted

技术标签:

【中文标题】使用 DownloadManager 从 S3 下载 apk 文件【英文标题】:Download apk file from S3 using DownloadManager 【发布时间】:2015-09-30 11:17:58 【问题描述】:

有没有办法使用 android 的 DownloadManager 从 S3 存储桶下载文件?

我目前可以这样做从 Dropbox 下载一个 apk 文件:

DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));

request.addRequestHeader("Content-Type", "application/vnd.android.package-archive");
request.setMimeType("application/vnd.android.package-archive");

final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long id = manager.enqueue(request);

现在我要做的是用我的亚马逊 URL 替换“url”。当我这样做时,下载只会停留在 0% 并卡在那里。

有没有办法做到这一点?

顺便说一下,我传入的亚马逊网址包含AWSAccessKeyIdExpiresSignature参数。网址如下所示:

https://bucket-name.s3-us-west-2.amazonaws.com/uploads/app/apk/22/app.apk?AWSAccessKeyId=""&Expires=""&Signature=""

【问题讨论】:

您是否尝试过纯 HTTP 而不是 HTTPS?您是否尝试过在您正在测试的设备或模拟器上的 Web 浏览器应用程序中访问 URL?您是否尝试过用于公共资源的 URL(即,不需要任何这些查询参数的 URL)?这些只是一些可能缩小问题范围的想法。 @CommonsWare 我刚刚尝试了你建议的一些事情。如果我单击 S3 存储桶中文件上的“公开”选项,则下载有效。这消除了对参数的需求。所以我假设问题与我的 AWS 凭证有关?尽管链接中有凭据,但该文件确实会下载到我计算机上的浏览器中。 “所以我假设问题与我的 AWS 凭证有关?” -- 我从未尝试过带有DownloadManager 的查询参数的URL。我会认为DownloadManager 会支持它。查看已解析的 UrigetQuery()getQueryParameters() 之类的内容,并确保您的值在此过程中不会被打乱。 @CommonsWare 好的,我刚刚查看了解析的 Uri 以及 getQueryParamters() 和 getQuery() 中的所有内容,一切似乎都很好。奇怪的是,我从来没有从 DownloadManager 得到错误或任何东西。它只是挂起。我想我会得到类似 401 或 403 错误之类的东西。 如果您可以找到其他一些涉及查询参数(不是 S3)的下载 URL,请试一试。如果失败,那么DownloadManager 可能对查询参数有限制。如果它成功了,那么DownloadManager 和 S3 之间涉及这些查询参数的握手就是罪魁祸首,尽管我真的不知道你会从那里去哪里。 【参考方案1】:

您好,您可以使用以下标头来获取请求中的apk文件。

Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:819457
Content-Type:application/octet-stream

【讨论】:

【参考方案2】:

失败的原因是您设置了Content-Type 标头。 HTTP 下载不需要此标头。但是,一旦设置,它就必须按照 AWS S3 的要求作为预签名 URL 中签名的一部分。否则你会看到 403 Forbidden - SignatureDoesNotMatch 错误。

快速的解决方案是删除Content-Type 标头。

request.addRequestHeader("Content-Type", "application/vnd.android.package-archive");

另一种解决方案是生成带有您需要的标头的预签名 URL。假设你真的想设置内容类型,你可以将它添加到 GeneratePresignedUrlRequest 然后从中创建一个 URL。

GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, key);
request.setContentType("application/vnd.android.package-archive");
URL url = s3Client.generatePresignedUrl(request);

更多详情请见AmazonS3.generatePresignedUrl(GeneratePresignedUrlRequest)。

【讨论】:

哇。谢谢这工作。你说这是“快速”的解决方案。我应该注意与此解决方案相关的任何问题吗?有没有更好的“更长”的解决方案?我对您的解决方案没有意见,只是想知道是否有什么我应该注意的。

以上是关于使用 DownloadManager 从 S3 下载 apk 文件的主要内容,如果未能解决你的问题,请参考以下文章

Downloadmanager实现app实现的升级下载使用

从 DownloadManager 打开下载的文件时如何修复 CursorIndexOutOfBoundsException? [复制]

DownloadManager不好用?试试ZlsamDownloadService

是否可以取消/停止使用 DownloadManager 开始的下载?

DownloadManager的使用

如何使用 DownloadManager 将下载的文件存储到应用程序分配的文件目录中?