LoginSignup
1
0

More than 5 years have passed since last update.

iPadからPDFデータをサーバに送信し、サーバ側はジェネリックハンドラで受信する(Swift2.2, XCode7.3.1 / VB.NET, ashx, VS2008)

Posted at

WKWebViewにHTML表示させ、PDF化する(Swift2.2, XCode7.3.1)のつづき

したいこと

iPad側でPDF作成して、Windowsサーバに送信する。
サーバ側はジェネリックハンドラ(ashx)で受信して、PDFを保存する。

サーバ側の処理をPHPで行えば、とても簡単にできました。
PHPの場合の参考URL
PHPがNGでジェネリックハンドラで処理しなければいけなかったので、苦労したのでメモしておきます。

コード

ViewController.swift
import UIKit
import WebKit

extension NSMutableData {
    func appendString(string: String) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
        appendData(data!)
    }
}

class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate {
    private var subView: UIView!
    private var webView: WKWebView!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        let size = view.frame.size
        subView = UIView(frame: CGRectMake(0, 0, size.width, size.height - 50))

        let btn = UIButton(type: .System)
        btn.frame = CGRectMake(0, size.height - 50, 90, 40)
        btn.setTitle("set HTML", forState: .Normal)
        btn.addTarget(self, action: #selector(ViewController.tapBtn(_:)), forControlEvents: .TouchUpInside)

        let btn2 = UIButton(type: .System)
        btn2.frame = CGRectMake(size.width * 0.35, size.height - 50, 90, 40)
        btn2.setTitle("set from web", forState: .Normal)
        btn2.addTarget(self, action: #selector(ViewController.tapBtn2(_:)), forControlEvents: .TouchUpInside)

        let btn3 = UIButton(type: .System)
        btn3.frame = CGRectMake(size.width * 0.7, size.height - 50, 90, 40)
        btn3.setTitle("create pdf", forState: .Normal)
        btn3.addTarget(self, action: #selector(ViewController.tapBtn3(_:)), forControlEvents: .TouchUpInside)

        view.addSubview(subView)
        view.addSubview(btn)
        view.addSubview(btn2)
        view.addSubview(btn3)

        webView = WKWebView()
        setupSubViews(subView)
    }

    internal func tapBtn(sender: UIButton) {
//        webView.loadHTMLString(getStrFromFile("test.html"), baseURL: nil)
        webView.loadHTMLString("hoge<br>piyo<br>foo<br>bar<br>hogeeeeeeeeeeeeeeeee", baseURL: nil)
    }

    internal func tapBtn2(sender: UIButton) {
        let req = NSURLRequest(URL: NSURL(string:"http://www.yahoo.co.jp/")!)
        webView.loadRequest(req)
    }

    internal func tapBtn3(sender: UIButton) {
//        let path = NSHomeDirectory().stringByAppendingString("/hoge.pdf")
//        PDFMaker.make([webView], path: path)

        // PDFファイルは作成せずにNSData化する
        let data = PDFMaker.make([webView])
        //        data.writeToURL(NSURL(fileURLWithPath: path), atomically: true)
        uploadPDF(data)
    }


    private func setupSubViews(v: UIView)
    {
//        webView.navigationDelegate = self
//        webView.scrollView.delegate = self
        webView.translatesAutoresizingMaskIntoConstraints = false
        v.addSubview(webView)
        var viewBindingsDict = [String: AnyObject]()
        viewBindingsDict["webView"] = webView
        v.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewBindingsDict))
        v.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewBindingsDict))
    }

    private func uploadPDF(pdfData: NSData) -> Bool {
        var ret = true

        let request = NSMutableURLRequest(URL: NSURL(string: "ashxファイルのURL")!)
        request.HTTPMethod = "POST"
        let param = [
            "userId" : "12345"
        ]
        let boundary = generateBoundaryString()
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", dataKey: pdfData, boundary: boundary)
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in
            if error != nil {
                print("error=\(error)")
                ret = false
            }
            print("******* response = \(response)")
            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
            print("****** response data = \(responseString!)")
            dispatch_async(dispatch_get_main_queue(),{
            });
        }
        task.resume()

        return ret
    }

    private func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, dataKey: NSData, boundary: String) -> NSData {
        let body = NSMutableData()
        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }
        //        let filename = "user-profile.jpg"
        let filename = "1234567890.pdf"
        //        let mimetype = "image/jpg"
        let mimetype = "application/pdf"
        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.appendData(dataKey)
        body.appendString("\r\n")
        body.appendString("--\(boundary)--\r\n")
        return body
    }

    private func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().UUIDString)"
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // プロジェクトに追加したローカルファイルの文字列取得
    private func getStrFromFile(fname: String) -> String {
        var ret = ""
        var path = NSString(string: fname)
        // Encode 日本語ファイル対応
        path = path.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
        let ext = path.pathExtension
        let filename = path.stringByDeletingPathExtension
        do {
            if let path = NSBundle.mainBundle().pathForResource(filename, ofType: ext) {
                ret = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
            }
        } catch {
            print("error getStrFromFile")
        }
        return ret
    }
}

// PDF作成クラス
class PDFMaker {
    private class func renderViews(views: [UIView]) {
        guard let context = UIGraphicsGetCurrentContext() else {
            return
        }
        views.forEach {
            if let scrollView = $0 as? UIScrollView {
                let tmpInfo = (offset: scrollView.contentOffset, frame: scrollView.frame)
                scrollView.contentOffset = CGPointZero
                scrollView.frame = CGRect(origin: CGPointZero, size: scrollView.contentSize)
                UIGraphicsBeginPDFPageWithInfo(scrollView.frame, nil)
                $0.layer.renderInContext(context)
                scrollView.frame = tmpInfo.frame
                scrollView.contentOffset = tmpInfo.offset
            } else {
                UIGraphicsBeginPDFPageWithInfo($0.bounds, nil)
                $0.layer.renderInContext(context)
            }
        }
    }

    class func make(views: [UIView], path: String) {
        UIGraphicsBeginPDFContextToFile(path, CGRectZero, nil)
        renderViews(views)
        UIGraphicsEndPDFContext()
    }

    class func make(views: [UIView]) -> NSData {
        let data = NSMutableData()
        UIGraphicsBeginPDFContextToData(data, CGRectZero, nil)
        renderViews(views)
        UIGraphicsEndPDFContext()
        return data
    }
}
サーバ側.ashx.vb
Imports System.Web
Imports System.Web.Services
Imports System.IO

Public Class emsapp
    Implements System.Web.IHttpHandler

    Private resp As HttpResponse = Nothing
    Private context As HttpContext = Nothing
    Private dirPath As String = System.Configuration.ConfigurationManager.AppSettings("dirPath")

    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        resp = context.Response
        Me.context = context
        context.Response.ContentType = "text/plain"


        If Not IO.Directory.Exists(dirPath) Then
            IO.Directory.CreateDirectory(dirPath)
        End If

        Dim files = context.Request.Files
        For i As Integer = 0 To files.Count - 1
            Dim file = files(i)
            Dim fnameTmp = context.Server.MapPath("~/" + file.FileName)
            file.SaveAs(fnameTmp)
            Dim fname = IO.Path.Combine(dirPath, file.FileName)

            If IO.File.Exists(fname) Then
                IO.File.Delete(fname)
            End If
            IO.File.Move(fnameTmp, fname)
            println(fname)
        Next

        '' PDFはできるが真っ白・・・
        'Dim str = New StreamReader(context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd()
        ''Dim sr As New System.IO.StreamReader(context.Request.InputStream)
        ''Dim str = New StreamReader(context.Request.InputStream).ReadToEnd
        'Dim path = IO.Path.Combine(dirPath, "hoge.pdf")
        ''Dim sw = New StreamWriter(path, True, System.Text.Encoding.ASCII)
        'Dim sw = New StreamWriter(path, True, System.Text.Encoding.Default)
        'sw.Write(str)
        'sw.Close()
    End Sub

    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

    Private Sub print(ByVal s As String)
        resp.Write(s)
    End Sub

    Private Sub println(ByVal s As String)
        resp.Write(s + vbCrLf)
    End Sub

End Class
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0