我们到底能走多远系列(19)
扯淡: 连续加班,效率急剧下降中.....
遇到存图片的问题,解决方案很多,时间太紧,从简单方式开始学习吧。
1,把图片存到数据库里,用的时候把它取出来。取出来有有个选择是需要一个零时文件来存,用路径在页面显示,这样问题比较多,不建议使用。
另一种方式就是直接把取出来的二进制文件传给页面,如下结合ibatis实现:
bean代码:
注意:license字段和identityCard字段是byte[],在数据库中我们采用clob来定义(orcale数据库)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; 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; 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);30px;"hidefocus></div>'); }
目前项目还在继续,很多图片的问题还没有解决,还在寻求比较好的方案中,特别有一个是图片剪切浏览这个,各位有好方案的,能发个链接,或指点一下,感激不尽。
让我们继续前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不会成功。
共勉。