我們到底能走多遠系列(19)
扯淡: 連續加班,效率急劇下降中.....
遇到存圖片的問題,解決方案很多,時間太緊,從簡單方式開始學習吧。
1,把圖片存到數據庫里,用的時候把它取出來。取出來有有個選擇是需要一個零時文件來存,用路徑在頁面顯示,這樣問題比較多,不建議使用。
另一種方式就是直接把取出來的二進制文件傳給頁面,如下結合ibatis實現:
bean代碼:
注意:license字段和identityCard字段是byte[],在數據庫中我們采用clob來定義(orcale數據庫)。

public class Dealer extends User { /** * */ private static final long serialVersionUID = -7791699407718373300L; private String contact; private String contactPhone; private String payee; private String accountNumber; private int bankType; private String bankName; private byte[] license; private byte[] identityCard; private String opinion; private Long industryId; private Long userId; private Long parentUserId; public int getBankType() { return bankType; } public void setBankType(int bankType) { this.bankType = bankType; } public byte[] getLicense() { return license; } public void setLicense(byte[] license) { this.license = license; } public byte[] getIdentityCard() { return identityCard; } public void setIdentityCard(byte[] identityCard) { this.identityCard = identityCard; } public String getContact() { return contact; } public void setContact(String contact) { this.contact = contact; } public String getContactPhone() { return contactPhone; } public void setContactPhone(String contactPhone) { this.contactPhone = contactPhone; } public String getPayee() { return payee; } public void setPayee(String payee) { this.payee = payee; } public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public String getBankName() { return bankName; } public void setBankName(String bankName) { this.bankName = bankName; } public String getOpinion() { return opinion; } public void setOpinion(String opinion) { this.opinion = opinion; } public Long getIndustryId() { return industryId; } public void setIndustryId(Long industryId) { this.industryId = industryId; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public Long getParentUserId() { return parentUserId; } public void setParentUserId(Long parentUserId) { this.parentUserId = parentUserId; } }
ibatis的sqlMap文件中一個正常的插入語句:
<insert id="addDealer" parameterClass="dealer"> insert into tb_Dealer (CONTACT, CONTACT_PHONE, PAYEE, ACCOUNT_NUMBER, BANK_TYPE, BANK_NAME, LICENSE, IDENTITY_CARD, OPINION,USER_ID,PARENT_USER_ID) values (#contact#, #contactPhone#, #payee#, #accountNumber#, #bankType#, #bankName#, #license#, #identityCard#, #opinion#,#userId#, #parentUserId#) </insert>
以下是示例代碼:把流寫到response里即可。
public ModelAndView showLicenseImage(HttpServletRequest request, HttpServletResponse response) { User user = (User) request.getSession().getAttribute("user"); Dealer dealer = dealerService.getById(user.getId()); byte[] license = dealer.getLicense(); try { ServletOutputStream outStream = response.getOutputStream(); response.setContentType("image/*"); // 設置返回的文件類型 outStream.write(license); // 輸出數據 } catch (IOException e) { e.printStackTrace(); } return null; }
這是頁面img標簽的寫法,注意src屬性,是后台地址
<img src="showCardImage.html" width="80" height="40" />
2,頁面 上傳圖片(就是文件嘛)
利用spring mvc的框架,比較輕松就可以實現:
control層的關鍵代碼:request轉型MultipartHttpServletRequest 取出MultipartFile,代碼還利用了spring的FileCopyUtils工具,實現相對路徑存數據庫,文件存文件夾。
// 處理上傳圖片 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; // 取得圖片 MultipartFile newImageFile = multipartRequest.getFile("newImage"); SimpleDateFormat df = new SimpleDateFormat(BusinessConstants.DATE_FORMAT); String filename = newImageFile.getOriginalFilename(); String file_ext = filename.substring(filename.lastIndexOf(BusinessConstants.DOT) + 1); // 圖片文件名 String imageName = newImageFile.getName() + df.format(new Date()) + BusinessConstants.DOT + file_ext; byte[] advImageBytes = null; InputStream advImageStream = null; // 存放圖片的路徑 File file = new File(request.getSession().getServletContext().getRealPath( BusinessConstants.IMAGE_FILE_PATH + imageName)); File oldFile = new File(request.getSession().getServletContext().getRealPath( BusinessConstants.IMAGE_FILE_PATH + oldImageName)); try { file.createNewFile(); advImageStream = newImageFile.getInputStream(); advImageBytes = FileCopyUtils.copyToByteArray(advImageStream); FileCopyUtils.copy(advImageBytes, file); advImageStream.close(); // 刪除原圖片 oldFile.delete(); } catch (IOException e) { e.printStackTrace(); }
對multipartResolver的配置如下:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設置上傳文件的最大尺寸為1MB --> <property name="maxUploadSize"> <value>1000000000000</value> </property> </bean>
在 Spring 中,MultipartResolver 主要用來處理文件上傳,它支持 Commons FileUpload (http://jakarta.apache.org/commons/fileupload) 和 COS FileUpload (http://www.servlets.com/cos)。 缺省中Spring是沒有multipart處理,因為一些開發者想要自己處理它們。
如果你想使用Spring的multipart,需要在web應用的上下文中添加multipart解析器。這樣,每個請求就會被檢查是否包含 multipart。然而如果請求中包含multipart,你的上下文中定義的MultipartResolver就會解析它。這樣你請求中的 multipart屬性就會象其它屬性一樣被處理。
說白了配置multipartResolver就是為了在上面的代碼可行:
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; // 取得圖片 MultipartFile newImageFile = multipartRequest.getFile("newImage");
特別注意點:
上傳的表單中必須指定其 enctype 為 mulitpart/form-data
3,button模擬file標簽,很多地方在上傳文件的按鈕是一個button,或者是圖片,可是ie對file有所謂的安全限制,如果是file觸發的事件涉及提交表單,就必須是鼠標真是點擊瀏覽按鈕過后。網上有人利用button的onclik事件指向file的onclik事件,來實現點擊button相當於點擊瀏覽,但是表單在file的onchange事件中無法提交。
所以有了以下的解決方案,原理是鼠標移動到button時,吧file按鈕帶到鼠標下,因為file按鈕設置成透明,這樣就可以實現實際點擊了:
看效果可以把opacity 設成50,你懂的。
html:
<div id="tt" style="position:relative; margin-right:400px;"> <input type="button" id="batchButton1" value="批量上傳" onmouseover="floatFile('file1')" style="height:28px; width:80px;"> <div id="div1"> <div id="file1text" ></div> <input id="file1" name="myfile" type="file" onchange="batchRelease()" style="position:absolute;filter:alpha(opacity=0);height:28px; width:40px;"> </div> </div>
js:
function floatFile(id) { document.getElementById(id).style.posTop=event.srcElement.offsetTop; document.getElementById(id).style.posLeft=event.x-document.getElementById(id).offsetWidth/2; } //選擇完一個文件之后,自動創建一個新的div 和 file表單,用於下回使用,hidden剛用過的file function showText(obj) { $(obj.id+"text").innerHTML=obj.value+" <a href='javascript:del("+fileNum+")'>刪除</a>"; $("file"+fileNum).style.display='none'; fileNum=fileNum+1; //直接追加innerHTML(innerHTML+=)會清空原來file中的內容 $("div"+(fileNum-1)).insertAdjacentHTML('AfterEnd','<div id="div'+fileNum+'"><div id="file'+fileNum+'text" ></div><input id="file'+fileNum+'" name="myfile" type="file" onchange="showText(this)" style="position:absolute;filter:alpha(opacity=0);width:30px;"hidefocus></div>'); }
目前項目還在繼續,很多圖片的問題還沒有解決,還在尋求比較好的方案中,特別有一個是圖片剪切瀏覽這個,各位有好方案的,能發個鏈接,或指點一下,感激不盡。
讓我們繼續前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不會成功。
共勉。