web应用图片存取体验-我们到底能走多远系列(19)

我们到底能走多远系列(19)

扯淡: 连续加班,效率急剧下降中.....

 

遇到存图片的问题,解决方案很多,时间太紧,从简单方式开始学习吧。

1,把图片存到数据库里,用的时候把它取出来。取出来有有个选择是需要一个零时文件来存,用路径在页面显示,这样问题比较多,不建议使用。

另一种方式就是直接把取出来的二进制文件传给页面,如下结合ibatis实现:

bean代码:

注意:license字段和identityCard字段是byte[],在数据库中我们采用clob来定义(orcale数据库)。
View Code
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+"&nbsp;&nbsp;<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>');
    }

 

目前项目还在继续,很多图片的问题还没有解决,还在寻求比较好的方案中,特别有一个是图片剪切浏览这个,各位有好方案的,能发个链接,或指点一下,感激不尽。

 

 

让我们继续前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不会成功。
共勉。

posted on 2013-01-11 09:14  每当变幻时  阅读(2543)  评论(6编辑  收藏  举报

导航