Tag Archive เมธอด

curl: ดาวน์โหลดไฟล์

การใช้ curl ไป download file จากเซิร์ฟเวอร์อื่นๆ ไม่ได้ซับซ้อนเหมือนการอัพโหลดในตัวอย่าง curl: ส่งไฟล์ การทำงานค่อนข้างตรงไปตรงมาก คือ มีไฟล์ที่มี code curl ทำหน้าที่ request และมีไฟล์หรือโปรแกรมที่ทำหน้าที่จ่ายไฟล์ให้ โดยดัดแปลงให้แสดง error กลับมาในรูปแบบที่ง่ายกับการแสดง error ในฝั่งรีเควสท์

เพื่อความปลอดภัย จะมีการเขียนการตรวจสอบเล็กน้อย

  • จะส่ง token มาและทั้ง 2 ไฟล์จะต้องมีค่าเท่าๆกัน ในความเป็นจริง ควรจะมีการเขียนที่ดีกว่านี้ เช่น เปลี่ยน token ตามช่วงเวลา
  • ไม่ควรให้ร้องขอไฟล์โดยใช้ full path และเพื่อป้องกันการใช้ฝั่งรับในการ download ไฟล์อื่นๆ จึงต้องกำหนดโฟลเดอร์เริ่มต้นไว้ให้ดาวน์โหลดไฟล์ในโฟลเดอร์ที่กำหนดไว้เท่านั้น
  • <?php
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Expires: 0');
    header('Pragma: no-cache');
    
    $post = [
        'file' => 'test.docx',
        'token' => $token,
    ];
    $token = 'HH89VOiirgXlCdEqDrFs';
    $url = 'http://localhost/snippets/PHP/download.php';
    
    $ch = curl_init();
    
    curl_setopt_array($ch, [
        CURLOPT_ENCODING => 'UTF-8',
        CURLOPT_FRESH_CONNECT => true,
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => http_build_query($post),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_URL => $url,
    ]);
    
    $result = curl_exec($ch);
    
    switch ($result) {
        case 'bad token':{
                curl_close($ch);
                exit('check token in ' . $url);
            }break;
    
        case 'file not found':{
                curl_close($ch);
                exit('file not found in target server.');
            }break;
    
        default:{
                header('Content-Disposition: attachment; filename="' . $post['file']);
                echo $result;
            }
    }
    curl_close($ch);

    <?php
    $fileDir = '../assets/';
    $token = 'HH89VOiirgXlCdEqDrFs';
    
    if ($_REQUEST['token'] != $token) {
        exit('bad token');
    }
    
    $file = $fileDir . $_REQUEST['file'];
    if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: ' . mime_content_type($file));
        header('Content-Disposition: attachment; filename="' . basename($file) . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
    
        //readfile($file);
        echo file_get_contents($file);
    } else {
        exit('file not found');
    }
    

curl: ส่งไฟล์

และแล้วก็มาถึงจุดที่รอคอย การส่งไฟล์ด้วย curl เหมือนที่ user upload ไฟล์เข้าเว็บ เหมาะกับการเอาไปเขียนโปรแกรมทรานสเฟอร์ไฟล์จากเว็บหนึ่งไปอีกที่หนึ่ง หรือจะเขียน bot ส่งไฟล์ออกไปเก็บเป็นข้อมูลสำรองก็ได้

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>CURL: send file</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
    <div class="container">
        <?php
if (count($_FILES) || count($_POST)) {
    $url = 'http://localhost/snippets/PHP/variables.php';

    if (count($_FILES)) {
        $file_name_with_full_path = $_FILES['avatar']['tmp_name'];

        if (function_exists('curl_file_create')) {
            /* php 5.5+ */
            $_POST['avatar'] = curl_file_create($file_name_with_full_path);
        } else {
            $_POST['avatar'] = '@' . realpath($file_name_with_full_path);
        }
    }

    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_ENCODING => 'UTF-8',
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => $_POST,
        //CURLOPT_POSTFIELDS => http_build_query($_POST),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_URL => $url,
    ]);

    $result = curl_exec($ch);
    curl_close($ch);

    echo $result;
}
?>
            <form action="curl_file.php" enctype="multipart/form-data" method="post">
                <div class="form-group">
                    <label for="name">Name:</label>
                    <input class="form-control" id="name" name="name" type="text">
                </div>
                <div class="form-group">
                    <label for="avatar">Avatar:</label>
                    <input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
                </div>
                <div class="form-group">
                    <label for="address1">text address:</label>
                    <input class="form-control" id="address1" name="address[d]" type="text">
                </div>
                <div class="form-group">
                    <label for="address2">text address 2:</label>
                    <input class="form-control" id="address2" name="address[f]" type="text">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
    </div>
</body>

</html>

แต่เพราะ bug ของ function http_build_query ไม่สามารถ encoded query string ในกรณีที่มีไฟล์ได้อย่างถูกต้อง ทำให้ต้องส่งค่าฟอร์มไปโดยไม่เข้ารหัส ดังนั้น ค่าที่เป็น array จึงส่งค่าออกไปผิด

[address]Array
(
    [name] => pitt phunsanit
    [address] => Array
)

จากที่ค้นหาข้อมูลดู ยังไม่มีวิธีที่แก้ปัญหานี้ได้โดยไม่มีผลอาการข้างเคียง คงต้องรอให้ทางทีมงานพัฒนา PHP แก้ปัญหาให้ ตอนนี้ก็พยามหลีกเลี่ยงการส่งข้อมูลแบบเป็นอาร์เรไปก่อน อาจจะใช้ implode รวมข้อมูลก่อนส่งไปก็ได้

curl: ส่ง ฟอร์มแบบ post

หลังจากตัวอย่าง curl: ส่ง ฟอร์มแบบ get เรามาลองส่งข้อมูลแบบโพสต์กันต่อ เว็บไซต์ส่วนใหญ่จะนิยมส่งค่าในแบบฟอร์มแบบ post มากกว่าแบบ get เพราะว่า url จะดูสวยงาม ไม่เละเทะ ดูแล้วสบายตา และปลอดภัยกว่าการส่ข้อมูลให้เห็นง่ายๆ แบบใช้ url

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>CURL: send post variables</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
    <div class="container">
        <?php
if (count($_POST)) {
    $url = 'http://localhost/snippets/PHP/variables.php';

    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_ENCODING => 'UTF-8',
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => http_build_query($_POST),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_URL => $url,
    ]);

    $result = curl_exec($ch);
    curl_close($ch);

    echo $result;
}
?>
            <form action="curl_post.php" enctype="multipart/form-data" method="post">
                <div class="form-group">
                    <label for="name">Name:</label>
                    <input class="form-control" id="name" name="name" type="text">
                </div>
                <div class="form-group">
                    <label for="avatar">Avatar:</label>
                    <input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
                </div>
                <div class="form-group">
                    <label for="address1">text address:</label>
                    <input class="form-control" id="address1" name="address[]" type="text">
                </div>
                <div class="form-group">
                    <label for="address2">text address 2:</label>
                    <input class="form-control" id="address2" name="address[]" type="text">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
    </div>
</body>

</html>

จากการเปลี่ยน option ของ curl เล็กน้อยการส่งข้อมูลก็เปลี่ยนไปเป็นแบบ method post แล้ว แต่ก็ยังส่งไฟล์ไปไม่ได้อยู่ดีๆ ใจเย็นๆ ครับบทความหน้าส่งไฟล์ออกไปแน่ๆ ครับ

curl: ส่ง ฟอร์มแบบ get

curl หรือ Client URL Library เป็น function ที่ทำให้ php ทำตัวเป็น browser ที่ใช้เปิดเว็บรับส่งข้อมูลต่างๆ จาก server ของเราไปเซิฟเวอร์เครื่องอื่นๆ

ตัวอย่างการใช้งานที่ง่ายที่สุด คือการใช้ curl โดยการจำลองการส่งข้อมูลจากฟอร์มแบบเมธอดเก็ต หรือที่เรียกง่ายๆว่า ส่งข้อมูลแบบ url นั่นละ

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>CURL: send get variables</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
    <div class="container">
        <?php
if (count($_GET)) {
    $queryString = http_build_query($_GET);
    $url = 'http://localhost/snippets/PHP/variables.php?' . $queryString;

    echo '<br>$url = ', $url;

    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_URL => $url,
    ]);

    $result = curl_exec($ch);
    curl_close($ch);

    echo $result;
}
?>
            <form action="curl_get.php" method="get">
                <div class="form-group">
                    <label for="name">Name:</label>
                    <input class="form-control" id="name" name="name" type="text">
                </div>
                <div class="form-group">
                    <label for="avatar">Avatar:</label>
                    <input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
                </div>
                <div class="form-group">
                    <label for="address1">text address:</label>
                    <input class="form-control" id="address1" name="address[]" type="text">
                </div>
                <div class="form-group">
                    <label for="address2">text address 2:</label>
                    <input class="form-control" id="address2" name="address[]" type="text">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
    </div>
</body>

</html>

ในการแปลงข้อมูลจากแบบฟอร์มจะใช้

$queryString = http_build_query($_GET);

แปลงให้อยู่ในรูปแบบคิวรี่สตริงที่ส่งไปกับ url ได้

การทดสอบทำได้โดยไฟล์ variables.php จำลองเป็นฝั่งรับข้อมูล

<?php
echo '<h3>$_COOKIE</h3><pre>', print_r($_COOKIE, true), '</pre>';
echo '<h3>$_FILES</h3><pre>', print_r($_FILES, true), '</pre>';
echo '<h3>$_GET</h3><pre>', print_r($_GET, true), '</pre>';
echo '<h3>$_POST</h3><pre>', print_r($_POST, true), '</pre>';
echo '<h3>$_REQUEST</h3><pre>', print_r($_REQUEST, true), '</pre>';

ข้อมูลที่ส่งไปจะแสดงกลับมาให้เราเห็น แต่สังเกตุได้ว่า ถึงจะส่งไฟล์ avatar ฝั่งรับก็จะไม่ได้รับ เพราะการส่งข้อมูลแบบนี้จะมีข้อเสียคือ ไม่สามารถส่งไฟล์ได้

laravel ajax method delete

เขียน ui laravel 5.1 อยู่ แบบใช้ ajax update ข้อมูล โดยเดิมมันใช้ form ธรรมดาแต่ใช้ method เป็น DELETE ทดลองส่งคำสั่งผ่าน ajax อยู่นานก็ไม่ได้ผล แถมมันวิ่งไปที่อื่นอีกตะหาก ทดลองเขียน php ธรรมดามาลองดูก็ไม่เจออะไร

นั่งงงอยู่นาน ก็ pass ค่าไปถูก เขียน php ธรรมดาไป ก็ได้ค่าไปถูก จน search ไปเจอ Delete request Jquery Ajax doesn’t work ที่แท้ laravel ถ้าจะใช้ method delete ต้องใช้ “method”: “POST” กับตัวแปร “_method”: “delete”

    $('.glyphicon-trash').click(function(e) {
        e.preventDefault();

        var r = confirm('Are you sure?');
        if(r == true) {
            $.ajax({
                "data": {
                    "_method":"DELETE",
                    "_token": "{{ csrf_token() }}",
                    },
                "success": function(result) {
                    location.reload();
                   alert('success');
                },
                "type": "POST",
                "url": "/admin/index",
            });
        }
    });

ใช้ได้แล้ว แต่น่าจะเขียนเป็นคู่มือเอาไว้นะ

เช็คฟอร์มด้วย jQuery Validation

ถ้าฟอร์มของเราโดนเรียกใช้บ่อยๆ การที่ใส่กฏไว้ในไฟล์ HTML จะทำให้ทราฟฟิคเว็บเราเสียไปเปล่าๆ แก้ได้โดยแยก rule ออกไปไว้ในไฟล์ javasscript เพราะว่าถึงหน้านี้จะโดนเรียกกี่ครั้ง แต่ไฟล์ javascript ที่โดนแยกออกไปจะโหลดแค่ครั้งเดียวเท่านั้น ประหยัดไปได้ส่วนหนึ่ง และทำให้โหลดหน้าเว็บได้เร็วขึ้น

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Validation  : html5 / inline</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
	<script src="http ://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<script src="http ://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<form action="validation.php" enctype="multipart/form-data" id="formA" method="post">
	<div class="form-group">
		<p>เครื่องปรุง</p>
		<label>
			<input type="checkbox" name="flavoring[]" value="1">
			เกลือ</label>
		<label>
			<input type="checkbox" name="flavoring[]" value="2">
			น้ำตาล</label>
		<label>
			<input type="checkbox" name="flavoring[]" value="3">
			น้ำปลา</label>
		<label>
			<input type="checkbox" name="flavoring[]" value="4">
			พริกป่น</label>
		<label for="flavoring[]" class="error"></label>
	</div>
	<div class="form-group">
		<label>สั่งวันที่
			<input type="text" name="dateOrder">
		</label>
	</div>
	<div class="form-group">
		<label>Email
			<input type="text" name="sendto">
		</label>
	</div>
	<div class="form-group">
		<label>รับเฉพาะภาพ
			<input type="file" name="image">
		</label>
	</div>
	<div class="form-group">
		<label class="btn btn-primary">รับแต่ .jpeg
			<input type="file" name="jpeg">
		</label>
	</div>
	<div class="form-group">
		<label>ข้าวเปล่า
			<input type="text" name="rice">
		</label>
	</div>
	<div class="form-group">
		<label>แคปหมู (ปลีก สั่งเป็นขีดได้ เช่น 0.5)
			<input type="text" name="friedPorkSkin">
		</label>
	</div>
	<div class="form-group">
		<label>แคปหมู (ส่ง kg.)
			<input type="text" name="friedPorkSkin">
		</label>
	</div>
	<div class="form-group">
		<p>เส้น</p>
		<label>
			<input type="radio" name="noodle" value="1">
			เส้นหมี่</label>
		<label>
			<input type="radio" name="noodle" value="2">
			เส้นเล็ก</label>
		<label>
			<input type="radio" name="noodle" value="3">
			เส้นใหญ่</label>
		<label>
			<input type="radio" name="noodle" value="4">
			เส้นหมี่</label>
		<label for="noodle" class="error"></label>
	</div>
	<div class="form-group">
		<label>เว็บส่วนตัว
			<input type="url" name="blogUrl">
		</label>
	</div>
	<button type="submit" class="btn btn-default">Submit</button>
</form>
<script src="assets/jQuery/jquery.min.js"></script>
<script src="plus/jQuery/jquery-validation/jquery.validate.min.js"></script>
<script src="assets/script.js"></script>
</body>
</html>

ไฟล์ assets/script.js

$(function()
{
	$('#formA').validate(
	{
		"messages" : {
			"friedPorkSkin" : {
				"digits" : "ขายแต่เป็น KG ครับ"
			}
		},
		"rules" : {
			"flavoring[]" : {
				"required" : true
			},
			"dateOrder" : {
				"required" : true,
				"date" : true
			},
			"sendto" : {
				"required" : true,
				"email" : true,
				"maxlength" : 50,
				"minlength" : 10
			},
			"image" : {
				"required" : true,
				"accept" : "image/*"
			},
			"jpeg" : {
				"required" : true,
				"accept" : "image/jpeg"
			},
			"rice" : {
				"required" : true,
				"number" : true
			},
			"friedPorkSkin" : {
				"required" : true,
				"digits" : true
			},
			"blogUrl" : {
				"required" : true,
				"url" : true
			}
		}
	});
});

ปล. messages โดนแยกออกมา ไม่เข้าใจเหมือนกันทำไม่ปลักอินตัวนี้ถึงออกแบบแบบนี้

jQuery Validation On AJAX form

ถ้าเราต้องการส่งค่าฟอร์มไปแบบเอแจ็กซ์ โดยก่อนส่งค่าไปให้ตรวจสอบเบื่องต้นก่อน สามารถทำได้โดยใช้เมธอด validate()

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Validation : AJAX form</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
      <script src="http://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="http://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<form action="login.php" id="formA" method="post">
	<div class="form-group">
		<label>User
			<input type="text" name="user" required minlength="5" maxlength="20">
		</label>
	</div>
	<div class="form-group">
		<label>Password
			<input type="password" name="password" required minlength="10" maxlength="50">
		</label>
	</div>
	<button type="submit" class="btn btn-default">Submit</button>
</form>
<script src="assets/jQuery/jquery.min.js"></script>
<script src="plus/jQuery/jquery-validation/jquery.validate.min.js"></script>
<script>
$(function()
{
	form = $('#formA');
	validation = form.validate();
	form.on('submit', function(event)
	{
		event.preventDefault();
		/* check form validation */
		if(validation.form() == true)
		{
			$.ajax({
				data: form.serialize(),
				dataType : 'json',
				success: function(data){
					$('#predictionCompaireA').html(data);
				},
				type: 'POST',
				url: 'login.php'
			});
		}
	});
});
</script>
</body>
</html>