js 選擇圖片並預覽、上傳

用火狐、谷歌調試圖片的預覽和上傳可謂是怎麼弄怎麼行,只要你說出需求,但是到了IE下,就出現了各類各樣的問題,可是無論你遇到什麼樣的問題,總會有解決的辦法,儘管有時候辦法可能會笨拙 、麻煩、費時、費力、很差看。html

選擇圖片固然很簡單,用一個input file標籤,點擊就會彈出文件選擇框。固然也不那麼簡單,每每咱們都嫌棄自帶按鈕很差看或是與你的操做邏輯不匹配,這就須要事件轉移或者是按鈕覆蓋。哎,從何提及呢?
java

火狐、谷歌……數據庫

頁面中加入文件選擇器標籤,opacity:0使標籤爲透明,也能夠display:none瀏覽器

<input type="file" id="choose-img" onchange="setImagePreview();" style="opacity:0">

將選擇按鈕的點擊事件轉移安全

button.onclick = function(){$("#choose-img").click()};

這樣按鈕的樣式就能夠徹底按你的喜愛來設置了,也能夠是連接、div、隨便服務器

文件選擇器的onchange事件
app

function setImagePreview(event) {
    var imagechoose=document.getElementById("choose-img");
 /*   var fileName = imagechoose.value;  
    if (!fileName.match(/.jpg|.jpeg|.gif|.png|.bmp/i)) {  
        alert('您上傳的圖片格式不正確,請從新選擇!');  
        return false;  
    }  */
    var imgObjPreview=document.getElementById("preview-img");    //預覽圖片的<img>
    
    if(imagechoose.files && imagechoose.files[0]){
    	var formData = new FormData();     // >=IE10 Partial support
    	formData.append("id",selectedId);
    	formData.append("file",imagechoose.files[0]);
        //火狐下,直接設img屬性
        //imgObjPreview.src = imagechoose.files[0].getAsDataURL();

        //火狐7以上版本不能用上面的getAsDataURL()方式獲取,須要一下方式
        imgObjPreview.src = window.URL.createObjectURL(imagechoose.files[0]);
    }
}

這樣在頁面上就能夠看到用戶選擇的圖片了,由於調用的是onchange事件,因此若是兩次選擇同一圖片是不會調用這個方法的,由於沒有change。函數

文件上傳使用了簡單方便的XMLHttpRequestpost

var xhrup = new XMLHttpRequest();
xhrup.open("POST", "後臺接收路徑");
xhrup.send(formData);    //上一個方法中保存的FormData,其餘參數也能夠一塊兒傳

也能夠添加回調函數,XMLHttpRequest上傳文件和請求文件都很好用ui

後臺接收

@RequestMapping("/uploadImage")
public @ResponseBody void uploadImage(MultipartHttpServletRequest request,HttpServletResponse response)throws Exception {
	try{
		Map getMap = request.getFileMap();
		String id = request.getParameter("id");
		MultipartFile mfile = (MultipartFile) getMap.get("file");
		InputStream file = mfile.getInputStream();
		byte[] fileByte = FileCopyUtils.copyToByteArray(file);
		Map<String, Object> setMap = new HashMap<String, Object>();
		setMap.put("id",id);
		setMap.put("file", fileByte);
		bulletinService.uploadImage(setMap);    //保存到數據庫
		operatelogService.addOperateLogInfo(request, "上傳成功:成功上傳圖片");
	}catch (Exception e) {
		e.printStackTrace();
		operatelogService.addOperateLogError(request, "上傳失敗:服務器異常");
	}
}

IE9

下面就要一項一項地說說以上方法都是如何不行的了。

若是你給input file設成了display:none,那它必定沒法給你彈出文件選擇對話框了,設成opacity:0才免爲其難能夠了,若是你設了opacity:0仍是能看見,不妨重啓機試試。

文件提交,不支持FormData格式,也獲取不到文件的byte數據,因爲它的安全機制,文件路徑和文件數據對你來講都是保密的,只能用form表單提交。提交後form的返回是一個頁面,若是不想刷新頁面,怎麼辦嘞,隱藏iframe。

事件轉移,是能夠的,不過,當你要提交表單的時候,它會檢查表單要提交的內容,這一檢查就檢查出問題了,它認定你的input file不是用戶選擇賦值,而是js人爲修改了它的值,因此在提交表單以前要清空你人爲修改的東西,也就是說,你選了,它也讓你選了,你要提交,它卻把你選的東西清了再提交,後臺什麼也收不到。

這樣事件轉移就不能用了,可使用按鈕覆蓋的方法,很麻煩,很差調。把input file設成opacity:0,在其上覆蓋你的按鈕或其餘,當用戶點擊你的按鈕時,實際是點擊到了input file的瀏覽按鈕。固然,也能夠直接用原生態的,就簡單了。

再說說這個預覽,剛開始我是用的獲取文件的真實全路徑,而後用濾鏡顯示。這個是能夠的,但後來因爲我不清楚的緣由,文件全路徑獲取不到了,簡直坑死。

因此我用了將文件上傳到服務器,再向服務器請求這個文件來顯示。麻煩,穩妥。

IE濾鏡預覽圖片

imagechoose.select();
imagechoose.blur();
 //       imgObjPreview.focus();
window.parent.document.body.focus();
//       window.top.document.body.focus();
var imgSrc = document.selection.createRange().text;    //這個理論上回獲取到文件的全路徑
 //       var imgSrc = $("#"+event.target.id).val();
        //必須設置初始大小
        imgObjPreview.style.width = ;
        imgObjPreview.style.height = ;
        //圖片異常的捕捉,防止用戶修改後綴來僞造圖片
imgObjPreview.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
imgObjPreview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc;

form表單

<form action="後臺接收路徑" id="" target="隱藏iframe的name" method="post" enctype="multipart/form-data">
<input type="file" id="" onchange="">
</form>


input file的onchange事件

var uploadform = document.getElementById("包含input的表單的ID");
uploadform.submit();

後臺接收

@RequestMapping("/uploadImage4ie")
public ModelAndView uploadImage4ie(@RequestParam("imgFile") MultipartFile imgFile,HttpServletRequest request,HttpServletResponse response)throws Exception {
	ModelAndView mav = new ModelAndView();
	mav.setViewName("返回頁面"); 
	try{
		String imgId = request.getParameter("imgId");
		byte[] imgByte = imgFile.getBytes();

		String cuid = CUID.cuid(4);
		//文件保存路徑
		String imagePath = (new File(this.getClass().getClassLoader().getResource("").toURI().getPath())).getParentFile().getParentFile().getPath()+"/images/docPreview/"+imgId+cuid+".jpg";
		FileImageOutputStream imageOutput = new FileImageOutputStream(new File(imagePath));
		imageOutput.write(imgByte, 0, imgByte.length);
		imageOutput.close();
		request.setAttribute("preId", imgId.substring(5));
		request.setAttribute("imgSrc", "images/docPreview/"+imgId+cuid+".jpg");
	        operatelogService.addOperateLogInfo(request, "上傳成功:成功上傳圖片");
        }catch (Exception e) {
		e.printStackTrace();
		operatelogService.addOperateLogError(request, "上傳失敗:服務器異常");
	}
	return mav;
}

隱藏iframe

<iframe name='nofreshIframe' style='display: none;'></iframe>

在返回頁面中設置預覽<img>的src爲請求圖片路徑

var src = document.getElementById("imgSrc").value;
var id = document.getElementById("preId").value;
var imgP = parent.document.getElementById(id);
imgP.src = src;
parent.setImgSrc(id,src);

這樣就基本完成了,IE是一項能把人累死和逼瘋的工做,漫漫長路,無窮無盡,真愛生命,遠離IE瀏覽器。

相關文章
相關標籤/搜索