使用带有参数的 NSURLSession (HTTP POST) 下载 PDF

Posted

技术标签:

【中文标题】使用带有参数的 NSURLSession (HTTP POST) 下载 PDF【英文标题】:Downloading PDF using NSURLSession (HTTP POST) with parameters 【发布时间】:2016-04-21 07:22:03 【问题描述】:

我在使用 NSURLSession 和 POST 下载 PDF 文件时遇到问题。我的下载网址与其他任何网址不同,因为它没有以文件扩展名结尾,并且还需要参数来下载该文件。

它来自 ASPX 基础服务器并像这样返回 url

http://example.com/DownloadPDF.aspx?File=ES2Ges%2BUA1CEe1150UF3uUgEDeCEMoIuOrJCbwjzVKCEfA6%2F1zKxycl6MMWcjvtk

如果我必须访问 pdf 并下载它,我必须提供 2 个参数 ConfigKeyIDAccessToken。奇怪的是它是 POST 请求。 因为,Alamofire 只支持GET 请求下载,所以,我必须使用NSURLSession 编写自己的自我。但是,我从我的代码访问文件时遇到问题,因为它返回带有 401 的 html 页面。

这里是html:

401 - 未经授权:由于凭据无效,访问被拒绝。

服务器错误

401 - 未经授权:由于凭据无效,访问被拒绝。

您无权使用您提供的凭据查看此目录或页面。

这是我的代码

protocol PDFDownloadAPIProtocol
    func didSuccessGettingPDF()
    func didFailGettingPDF(err:NSError)


class PDFDownloadAPI

var delegate : InvoicePDFDownloadAPIProtocol

init(delegate: InvoicePDFDownloadAPIProtocol)
    self.delegate=delegate


func post(url:String,accessToken:String,configKey :String)
    let url:NSURL = NSURL(string: url)!

    print(url)
    let session = NSURLSession.sharedSession()

    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData

    let param = "ConfigKeyID=\(configKey)&AccessToken=\(accessToken)"
    request.HTTPBody = param.dataUsingEncoding(NSUTF8StringEncoding)

    let task = session.downloadTaskWithRequest(request) 
        (
        let location, let response, let error) in

        guard let _:NSURL = location, let _:NSURLResponse = response  where error == nil else 
            print("Location Error")
            self.delegate.didFailGettingPDF(error!)
            return
        

        let urlContents = try! NSString(contentsOfURL: location!, encoding: NSUTF8StringEncoding)

        guard let _:NSString = urlContents else 
            print("Content Error")
            self.delegate.didFailGettingPDF(error!)
            return
        

        print("Downloaded Content : \(urlContents)")

        self.delegate.didSuccessGettingPDF()
    

    task.resume()


func doDownloadData(url : String,accessToken:String,configKey : String)
    post(url,accessToken: accessToken,configKey : configKey)


当我尝试使用 Postman 一切工作文件时,我什至可以从 chrome 下载文件。所以,我认为我的代码有问题。有什么帮助吗?

【问题讨论】:

【参考方案1】:

很有可能,身份验证需要的不仅仅是 POST 请求字段。它可能使用 cookie 或身份验证标头(基于实际凭据)。

如果我错了,我会检查以下内容:

在将这两个魔法值添加到 POST 正文之前,请确保它们已正确进行 URL 编码。 确保设置 Content-Type 标头,以便服务器知道您提供的是 x-www-form-urlencoded 格式的正文。 使用 Wireshark 嗅探请求,查看实际发送的内容。 如果可以,请检查服务器日志。

【讨论】:

以上是关于使用带有参数的 NSURLSession (HTTP POST) 下载 PDF的主要内容,如果未能解决你的问题,请参考以下文章

带有令牌认证的 NSURLSession

带有 NSURLSession 的 Swift 中的 HTTP 请求

带有 NSURLSession 的 Http/2 server_push

带有 URL 的 NSURLSession downloadTask 返回 nil

NSURLSession下载文件-代理

使用 NSURLSession 发送 POST 请求