後台上傳圖片時,若想要看到預覽圖片,早期只有 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。
沒有留言:
張貼留言