後台上傳圖片時,若想要看到預覽圖片,早期只有 IE 有 function 可以吃到 localhost 的檔案,讓你看到你要上傳的圖片樣貌,現在 HTML5 有 FileReader 的 api 可以用,範例如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
var allows = ['jpg', 'jpeg', 'gif', 'png'];
$('#file').on('change', function() {
var reader = new FileReader();
var ext = $(this).val().split('.').pop().toLowerCase();
try {
if ($.inArray(ext, allows) === -1) {
throw new Error('檔案格式錯誤,僅允許' + allows.join(', '));
}
reader.readAsDataURL(this.files[0]);
reader.onload = function(e) {
$('#content').html('<img src="' + e.target.result + '">');
}
} catch (e) {
alert(e.message);
}
});
});
</script>
</head>
<body>
<input id="file" type="file" name="file">
<div id="content"></div>
</body>
</html>
這個方法有幾個問題:
- 瀏覽器支援問題
- 真實呈現問題(假設我們有透過後端處裡圖片無法呈現最後樣貌)
基於以上兩點,我決定還是透過 ajax + php 的方法來做掉,我的方法是,檔案 onChange 的時候 upload 去 server 端,請 server 端處理 tmp_name,然後傳回 base64_encode 的結果,這樣的好處是檔案我沒有使用 move 搬移,server 會自動幫我定期清除那些暫存檔,使用 base64 編碼因此不需要衍生其他檔案,做法如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/3.51/jquery.form.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
$('#file').on('change', function() {
$('#frm').ajaxSubmit({
url: 'preview.php',
success: function(response) {
if (response.status !== 'done') {
alert(response.message);
} else {
$('#content').html('<img src="' + response.message + '">');
}
}
});
return false;
});
});
</script>
</head>
<body>
<form id="frm" method="post" action="upload.php">
<input id="file" type="file" name="file">
</form>
<div id="content"></div>
</body>
</html>
php
<?php
header('Content-Type: application/json');
include 'vendor/autoload.php';
$status = 'done';
$message = '';
$allows = ['jpeg', 'png', 'gif'];
$file = $_FILES['file'];
$map = function($item) {
return "image/{$item}";
};
try {
if ($file['name'] === '') {
throw new Exception("請選擇檔案");
}
$type = $file['type'];
if (!in_array($type, array_map($map, $allows))) {
throw new Exception('檔案格式錯誤,僅接受'.implode(', ', $allows));
}
$layer = PHPImageWorkshop\ImageWorkshop::initFromPath($file['tmp_name']);
$layer->resizeInPixel(100, null, true, 0, 0, 'MM');
$result = $layer->getResult();
ob_start();
call_user_func(str_replace('/', '', $type), $result);
$image = ob_get_contents();
ob_end_clean();
$message = "data:{$type};base64,".base64_encode($image);
} catch (Exception $e) {
$status = 'fail';
$message = $e->getMessage();
}
echo json_encode(compact('status', 'message'));
我使用了 ImageWorkshop 來處理縮圖等等的功能,這個部分可以自行替換 solution。
沒有留言:
張貼留言