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>');
    }

 

目前項目還在繼續,很多圖片的問題還沒有解決,還在尋求比較好的方案中,特別有一個是圖片剪切瀏覽這個,各位有好方案的,能發個鏈接,或指點一下,感激不盡。

 

 

讓我們繼續前行

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM