質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.36%

swiftにて画像アップロード(サーバ上へ)

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 5,847

score 27

以前に質問した内容に近いのですが、またご教授いただければ幸いです。

下記のサイトを参考にしながら、ファイルのアップロードをしたいと考えております。
【Swift】Swift + PHPでiOSから画像をアップロードする

シミュレータ上では、動作はしているのですが、画像が指定したファイル(/Applications/MAMP/htdocs/uploadfile)に保存されておりません。
エラーのメッセージも出ずで、どのように対応したらいいのかご教授いただければ幸いです。

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
    @IBOutlet weak var myImageView: UIImageView!
    var imageForUpload: UIImage!

    @IBOutlet weak var imageview: UIImageView!    
    override func viewDidLoad() {
        super.viewDidLoad()

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func uploadButtonTapped(sender: AnyObject) {        
        myImageUploadRequest()   
    }

    @IBAction func selectPhotoButtonTapped(sender: AnyObject) {
        let myPickerController = UIImagePickerController()
        myPickerController.delegate = self;
        myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary

        self.presentViewController(myPickerController, animated: true, completion: nil)
    }
    //画像のアップロード処理
    func myImageUploadRequest(){

        //myUrlには自分で用意したphpファイルのアドレスを入れる
        let myUrl = NSURL(string:"http://http://localhost/upload.php")
        let request = NSMutableURLRequest(URL:myUrl!)
        request.HTTPMethod = "POST"
        //下記のパラメータはあくまでもPOSTの例
        let param = [
            "userId" : "1234"
        ]

        let boundary = generateBoundaryString()

        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        let imageData = UIImageJPEGRepresentation(self.imageForUpload, 1)

        if(imageData==nil) { return; }
        request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)

        //myActivityIndicator.startAnimating();
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in
            if error != nil {
                print("error=\(error)")
                return
            }
            // レスポンスを出力
            print("******* response = \(response)")
            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
            print("****** response data = \(responseString!)")

            dispatch_async(dispatch_get_main_queue(),{
                //アップロード完了
            });
        }
        task.resume()

    }
    func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: 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 mimetype = "image/jpg"
        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(imageDataKey)
        body.appendString("\r\n")
        body.appendString("--\(boundary)--\r\n")
        return body
    }

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

    //カメラで写真を取る
    func pickImageFromCamera() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            let controller = UIImagePickerController()
            controller.delegate = self
            controller.sourceType = UIImagePickerControllerSourceType.Camera
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }

    //写真をライブラリから選択
    func pickImageFromLibrary() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
            let controller = UIImagePickerController()
            controller.delegate = self
            controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }
    //画像が選択されたら呼び出される
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        if info[UIImagePickerControllerOriginalImage] != nil {
            let image = info[UIImagePickerControllerOriginalImage] as! UIImage

            //iamgeForUploadというUIImageを用意しておいてそこに一旦預ける
            self.imageForUpload = image
            self.myImageUploadRequest()
        }
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
}
    extension NSMutableData {
        func appendString(string: String) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
        appendData(data!)
        }
 }

以下ファイルは、/Applications/MAMP/htdocs/upload.phpとして、おいております。

<?php
$userId = $_POST["userId"];

//下記のディレクトリ名は好きなものでOK
$target_dir = "/uplodafile";
if(!file_exists($target_dir))
{
mkdir($target_dir, 0777, true);
}
 $target_dir = $target_dir . "/" . basename($_FILES["file"]["name"]);

if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir)) {
echo json_encode([
"Message" => "The file ". basename( $_FILES["file"]["name"]). " has been uploaded.",
"Status" => "OK",
"userId" => $_POST["userId"]
]);

} else {

echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_POSt["userId"]
]);
}
?>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2016/08/15 09:11

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

+1

載せているコードがmultipartを利用したやり方でしたが、簡単に画像だけをアップロードしたいのでしたら以下のサイトを参考にしたほうが解決が早いかもしれません。

Swift Docs 009 ファイルのアップロード

自分はphpは全く分かりませんが、以下の様にすることで取り合えず画像はアップロードできました。
まず最低限動くものを作ってからアレンジしたほうが近道かもしれませんね。

MAMPの設定はポートのApacheポートを80にしました。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let image = UIImage(named: "swift")!

        let url = NSURL(string: "http://localhost:80/upload.php")!
        let request = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "POST"

        let imageData = UIImageJPEGRepresentation(image, 1.0)!

        let session = NSURLSession.sharedSession()
        let tasK = session.uploadTaskWithRequest(request, fromData: imageData) { (data, response, error) in

            print(NSString(data: data!, encoding: NSUTF8StringEncoding))

            if let error = error {
                print(error.description)
            }
        }
        tasK.resume()
    }
}


upload.php

<?php
    // リクエストBodyからファイルのデータを取得.
    $image = file_get_contents("php://input");

    // 取得したバイナリデータを画像(png)として保存.
    file_put_contents('dl.png',$image);
?>

質問されているコードで実行

以下のコードで問題なくMAMPのフォルダに指定したフォルダが作られて画像がアップロードされました。
やはりMAMPのサーバーに問題なく繋がることを確認してから該当サイトのコードを試すほうが確実なような気がします。

ViewController.swift

import UIKit
import Foundation

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

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{

    // 画面にUIImageViewを配置
    @IBOutlet weak var imageForUpload: UIImageView!

    // Photo Libraryを開く為のボタンアクションを追加
    @IBAction func openLibrary(sender: UIButton) {
        pickImageFromLibrary()
    }



    // ---------- 以下はアクセスするサイトURL以外は変更なし ------------




    //UIImagePickerControllerDelegate, UINavigationControllerDelegateを忘れずに
    //画像のアップロード処理
    func myImageUploadRequest(){
        //myUrlには自分で用意したphpファイルのアドレスを入れる
        let myUrl = NSURL(string: "http://localhost:80/upload.php")!
        let request = NSMutableURLRequest(URL:myUrl)
        request.HTTPMethod = "POST"
        //下記のパラメータはあくまでもPOSTの例
        let param = [
            "userId" : "12345"
        ]
        let boundary = generateBoundaryString()
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        let imageData = UIImageJPEGRepresentation(self.imageForUpload.image!, 1)
        if(imageData==nil) { return; }
        request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in
            if error != nil {
                print("error=\(error)")
                return
            }
            // レスポンスを出力
            print("******* response = \(response)")
            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
            print("****** response data = \(responseString!)")
            dispatch_async(dispatch_get_main_queue(),{
                //アップロード完了
            });
        }
        task.resume()
    }
    func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: 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 mimetype = "image/jpg"
        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(imageDataKey)
        body.appendString("\r\n")
        body.appendString("--\(boundary)--\r\n")
        return body
    }
    func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().UUIDString)"
    }
    //カメラで写真を取る
    func pickImageFromCamera() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            let controller = UIImagePickerController()
            controller.delegate = self
            controller.sourceType = UIImagePickerControllerSourceType.Camera
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }

    //写真をライブラリから選択
    func pickImageFromLibrary() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
            let controller = UIImagePickerController()
            controller.delegate = self
            controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }
    //画像が選択されたら呼び出される
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        if info[UIImagePickerControllerOriginalImage] != nil {
            let image = info[UIImagePickerControllerOriginalImage] as! UIImage
            //iamgeForUploadというUIImageを用意しておいてそこに一旦預ける
            self.imageForUpload.image = image
            self.myImageUploadRequest()
        }
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
}

upload.php

<?php
$userId = $_POST["userId"];
//下記のディレクトリ名は好きなものでOK
$target_dir = "wp-content/uploads/2015/02";
if(!file_exists($target_dir))
{
mkdir($target_dir, 0777, true);
}

$target_dir = $target_dir . "/" . basename($_FILES["file"]["name"]);

if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir)) {
echo json_encode([
"Message" => "The file ". basename( $_FILES["file"]["name"]). " has been uploaded.",
"Status" => "OK",
"userId" => $_POST["userId"]
]);

} else {

echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_POSt["userId"]
]);
}
?>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/20 16:57

    連絡が遅くなり大変申し訳ございません。返信ありがとうございます。
    上記コードにて、ファイルアップロードすることであればうまく機能しました。
    今回の質問で試してみたのですが、以下エラーメッセージでした。
    エラー修正して、再度チャレンジしてみます。ご回答ありがとうございました。

    ****** response data = {"Message":"Sorry, there was an error uploading your file.","Status":"Error","userId":null}

    キャンセル

0

このURLは恐らく間違いだと思います。
let myUrl = NSURL(string:"http://http://localhost/upload.php")

エラーログが出ないというのであれば、どの行までは正しく実行されるのかを順番に確かめるしかないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/20 16:59 編集

    コメントありがとうございます。
    連絡が遅くなり申し訳ありません。

    ご指摘の通り、URLが誤っておりました。修正いたしました。
    上記で書いたエラーが出てきておりますので、デバックも勉強中ですが、少しずつチャレンジしてまいります。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る