顯示廣告
隱藏 ✕
看板 Knuckles_note
作者 Knuckles (站長 那克斯)
標題 [JS] 單鍵上傳圖片 上傳前使用canvas縮圖
時間 2015年02月15日 Sun. AM 07:04:53


點一個按鈕選好檔案就開始上傳圖片
並且限制圖檔大小,太大會縮小後再上傳

範例頁: http://knuckles.disp.cc/test/imgur/imgUpload.php

在網頁上使用表單上傳圖片時:
<form id="uploadForm" name="uploadForm" action="imgur_upload_multiple.php" enctype="multipart/form-data" method="POST">
<input type="file" id="uploadInput" name="fileData[]" size="35" accept="image/*" multiple />
<input type="submit" name="submit" value="上傳"/>
</form>

結果像這樣:
[圖]

要先點「選擇檔案」後,還要再點「上傳」,圖片才會上傳

如果想要選擇檔案後,就直接開始上傳的話
可以只放一個 type="file" 的 input

<div class="oneClickUpload">
<input type="file" name="fileData[]" size="35" accept="image/*" multiple />
</div>

然後在 Javascript 利用 input 的 onChange 事件來執行上傳圖片

<script type="text/javascript">
//前面要先載入 jQuery
$(function(){
	
$('.oneClickUpload > input').on('click',function(){
	
	
this.value = null;
	
}).on('change',function(){
	
	
var files = this.files;
	
	
var i, file;
	
	
for(i=0; i<files.length; i++){
	
	
	
file = files[i];
	
	
	
if(!file.type.match(/^image/)){ //去除非圖片檔
	
	
	
	
console.log('file '+(i+1)+' is not an image');
	
	
	
	
continue;
	
	
	
}
	
	
	
//將 file 上傳,取得圖片網址
	
	
	
imgFileUpload(file, { 
	
	
	
	
action: 'imgur_upload_base64.php',
	
	

	
	
	
	
onSubmit: function(){
	
	
	
	
	
//選好檔案後要做的事
	
	
	
	
}, 
	
	
	
	
onComplete: function(responseJSON){
	
	
	
	
	
//上傳完成後要做的事
	
	
	
	
}
	
	
	
});
	
	
}
	
});
});

function imgFileUpload(file,options){ ... } //上傳圖片的程式,寫在後面

</script>

如果想要自訂上傳按鈕的樣式的話
可以產生一個自訂的按鈕,然後再把隱形的 input 放在上面
例如:

單鍵上傳:
<div class="oneClickUpload">
<input type="file" name="fileData[]" size="35" multiple />
<div class="oneClickUpload-inner">上傳圖片</div>
</div>

<style type="text/css">
.oneClickUpload{
	
display: inline-block; width:70px; height: 26px; cursor: pointer;
	
background-color: red; font-size: 16px;
	
border: 1px solid black; border-color: rgba(0,0,0,0.25);
	
-webkit-border-radius: 0.25em; -moz-border-radius: 0.25em; border-radius: 0.25em;
}
.oneClickUpload > input { 
	
opacity: 0; font-size: 0; cursor: pointer;
	
position: absolute; width: 70px; height: 26px;
}
.oneClickUpload-inner{
	
padding: 3px; text-align: center; vertical-align: middle;
}
</style>

將 input 設為 opacity: 0; font-size: 0;
並將大小與位置設成剛好可以覆蓋住自訂的按鈕即可
結果會像這樣:
[圖]



接著將 input 讀到的 file 傳給 function imgFileUpload() 來上傳圖片
可設定寬度與高度的上限,若上傳的圖片太大時先會縮小後再上傳
參考: http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/

加上一個textarea用來接收回傳的圖片網址
上傳圖片的網址:
<textarea id="upload-result"></textarea>

選好擋案時會先在 textarea 插入字串 [img {id} uploading...]
其中 id 為 imgFileUpload 中隨機產生的字串,用來辨別不同的上傳檔案
等上傳成功後再將這個字串改為回傳的圖片網址

修改 imgFileUpload 輸入的 onSubmit 和 onComplete 為

	
var uploadResult = document.getElementById('upload-result');
	
imgFileUpload(file, { 
	
	
action: 'imgur_upload_base64.php',
	
	

	
	
onSubmit: function(id){ //選好檔案後要做的事
	
	
	
var anchor_str = "[img "+id+" uploading...]\n";
	
	
	
uploadResult.value += anchor_str;
	
	
}, 
	
	
onComplete: function(responseJSON,id){ //上傳完成後要做的事
	
	
	
var data = responseJSON.data;
	
	
	
if(!responseJSON.success){ alert(data.error); }
	
	
	
var anchor_str = "[img "+id+" uploading...]\n";
	
	
	
var bbcode = '[img='+data.width+'x'+data.height+']'+data.link+"[/img]\n";
	
	
	
uploadResult.value = uploadResult.value.replace(anchor_str,bbcode);
	
	
}
	
});


用來上傳圖片的 function imgFileUpload() 程式碼:

<script type="text/javascript">
function imgFileUpload(file, options){
	
$.extend({ //options 預設值
	
	
action: 'imgur_upload_base64.php', //上傳圖片的網址
	
	
maxWidth: 1000, //寬度預設最大1000px
	
	
maxHeight:0,    //高度預設無限制
	
	
onSubmit: function(){}, //選好檔案時要做的事
	
	
onComplete: function(){}//上傳完成後要做的事
	
}, options);
	
var type = file.type;
	
var src = window.URL.createObjectURL(file);
	
//隨機產生一個id,用來辨別不同的上傳檔案
	
var id = Math.random().toString(36).substring(3,7);
	

	
options.onSubmit(id);

	
var img = document.createElement("img");
	
img.src = src;
	
img.onload = function(){
	
	
var width = this.width,
	
	
	
height = this.height,
	
	
	
maxWidth = options.maxWidth,
	
	
	
maxHeight = options.maxHeight;
	
	
//寬或高大於設定的上限時,等比例縮小到符合上限
	
	
if(width > height){
	
	
	
if(maxWidth>0 && width>maxWidth){
	
	
	
	
height *= maxWidth / width;
	
	
	
	
width = maxWidth;
	
	
	
}
	
	
}else{
	
	
	
if(maxHeight>0 && height>maxHeight){
	
	
	
	
width *= maxHeight / height;
	
	
	
	
height = maxHeight;
	
	
	
}
	
	
}
	
	
//使用縮小後的寬高建立一個canvas
	
	
var canvas = document.createElement("canvas");
	
	
canvas.width = width;
	
	
canvas.height = height;
	
	
var ctx = canvas.getContext("2d");
	
	
ctx.drawImage(img, 0, 0, width, height);
	
	
//將canvas轉為圖片的base64編碼
	
	
var dataurl = canvas.toDataURL(type); 
	
	
//去掉 dataurl 開頭的 data:image/png;base64,
	
	
var regex = new RegExp('^data:'+type+';base64,');
	
	
var base64 = dataurl.replace(regex,'');
	
	
//將圖片的base64編碼上傳至網站,將回傳的JSON傳至onComplete
	
	
$.post(options.action, {base64:base64}, function(responseText){
	
	
	
if(!responseText.match(/^[\{\[]/)){ alert(responseText); return; }
	
	
	
var responseJSON = JSON.parse(responseText);
	
	
	
options.onComplete(responseJSON,id);
	
	
},'text');
	
};
}

</script>

其中使用了 canvas 來縮小圖片大小
然後將 canvas 轉為圖片的 base64 編碼
最後將 base64 傳給網站的 imgur_upload_base64.php

<?php // imgur_upload_base64.php
$image_base64 = isset($_POST['base64'])? $_POST['base64'] : '';
if(!$image_base64){ die('base64 error'); }
$imgur_result = imgur_upload($image_base64);
echo $imgur_result;

//利用 Imgur API 上傳圖片的程式,請參考 http://disp.cc/b/11-8qWb
function imgur_upload(){ ... }


改寫成 jQuery plugin 可參考: http://disp.cc/b/11-8uGt


--
※ 作者: Knuckles 時間: 2015-02-15 07:04:53
※ 編輯: Knuckles 時間: 2015-10-23 05:43:36
※ 看板: KnucklesNote 文章推薦值: 0 目前人氣: 0 累積人氣: 4648 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇