web-上傳文件

總結

上傳文件,本質上都是包含以幾個步驟:
1.客戶端向服務器發送http請求
2.客戶端向請求路徑寫二進制數據
3.服務器讀二進制數據
寫數據到磁盤(即保存文件到服務器)
保存文件路徑到數據庫表的路徑字段html

下面介紹幾個實際應用場景。java

web

1.基於開源file-upload實現
封裝了讀二進制流的處理
最後,獲得文件項集合List<FileItem>android

2.基於struts2實現
也是基於開源file-upload
只不過結合struts2,封裝得更加好用
最後,獲得文件數組File[] web

File[]是Action類的數據 算法

3.基於springMVC實現
同struts2spring

合夥人二維碼

功能描述

生成二維碼圖片數據庫

實現思路

1.第一次訪問
1)生成二維碼
保存二維碼到服務器
2)保存二維碼路徑到數據庫apache

2.第二次訪問
根據數據庫的路徑字段,訪問服務器二維碼存放路徑數組

代碼

控制器瀏覽器

/**
     * 
     * <pre>
     * 生成合夥人二維碼
     * </pre> 
     * @author gzh
     * @date 2017年3月30日下午8:33:29
     */
    public String doGenerateHeHuoRenQRcode() throws IOException {
        try {
            ProxyUser proxyUser = (ProxyUser) getSessionAttribute("proxyUser");
            
            //判斷是否已經生成二維碼
            Proxy proxy2 = proxyService.getProxyById(proxyUser.getProxyId());
            if (proxy2.getQrCode() != null) { //已生成
                //輸出數據
                String imgUrl = ConfigUtil.PROXY_LOOKPATH_QRCODE + File.separator + proxy2.getQrCode();
//                imgUrl = imgUrl.replaceAll("\\\\", "/");
                setRequestAttribute("imgUrl", imgUrl);
            }else { //未生成
                if(!isNotNullOrEmpty(proxyUser.getInviteCode())){
                    proxyUserService.updateProxyUserInviteCode(proxyUser);
                }
                
                ProxyUser pu = proxyUserService.getProxyUser(proxyUser);
                
                // 生成二維碼
                StringBuffer toHeHuoRenUrl = new StringBuffer(ConfigUtil.TO_HEHUOREN_URL_QRCODE); //代理商-生成二維碼圖片的路徑
                //toHeHuoRenUrl.append(proxyUser.getId());
                toHeHuoRenUrl.append(pu.getInviteCode());
                String logoPath = "";// 二維碼Logo
                StringBuffer imgPath = new StringBuffer(ConfigUtil.PROXY_UPLOADPATH_QRCODE);// 代理商-二維碼圖片的上傳路徑
                String date = DateUtils.getInstance().today1();
                
                //判斷日期目錄是否存在
                File dateDir = new File(imgPath + File.separator + date);
                if (!dateDir.exists()) { //不存在
                    dateDir.mkdirs();
                }
                
                String imgName = date + File.separator + UuidGenerator.getUuidGenerator() + "." + IMAGE_TYPE; // 圖片名稱
                imgPath.append(File.separator).append(imgName);
                
                

                try {
                    QRCodeComm.encoderQRCode(toHeHuoRenUrl.toString(), imgPath.toString(), IMAGE_TYPE, logoPath);
                } catch (Exception e) {
                    log.error("HeHuoRen.doGenerateHeHuoRenQRcode() error " + e); 
                    return "";
                }
                
                //保存二維碼路徑
                Proxy proxy = new Proxy();
                proxy.setId(proxyUser.getProxyId());
                proxy.setQrCode(imgName.toString());
                int result = proxyService.updateProxy(proxy);
                if (result == 0) {
                    log.error("HeHuoRen.doGenerateHeHuoRenQRcode() error: update t_proxy failed!");
                }
                
                //輸出數據
                String imgUrl = ConfigUtil.PROXY_LOOKPATH_QRCODE + File.separator + imgName;
                setRequestAttribute("imgUrl", imgUrl);
            }
        } catch (Exception e) {
            log.error("doGenerateHeHuoRenQRcode() error", e);
            return "";
        }
        return "success";
    }

app

進件

功能描述

向第三方支付通道進件
第三方支付向銀行通道或其餘第三方支付通道(例如,支付寶和微信)進件

實現思路

1.app發送請求
1)http請求路徑
2)往請求路徑寫二進制流
3)http請求對象的內容類型content-type字段,須要設置爲多媒體類型

2.後臺接收請求
1)基於上傳文件開源框架-apache fileupload讀二進制流
上傳文件框架會把二進制流轉換爲文件對象(框架裏的文件對象,與jdk的File不是一個東西)
2)從文件對象取文件流
3)讀文件流
4)寫數據到服務器磁盤

代碼

後臺控制器代碼
注:app發送http請求時,確保2點,1.往請求路徑寫二進制流數據 2.請求類型字段content-type的值,設置爲多媒體類型

package com.dinpay.dpp.cpmobile.action.cpinfo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dinpay.dpp.pmsmobile.comm.PmsBaseAction;

/**
 * 
 * <pre>
 * 類的名稱:
 * 類的做用:進件
 * 1.商家進件到第三方支付公司通道
 * 2.第三方支付公司通道再把數據進件到支付寶和微信
 * </pre>
 * 
 * @author gzh
 * @date 2017年12月21日下午12:00:47
 */
public class IntoPieceAction extends PmsBaseAction {
    /**
     * 
     */
    private static final long serialVersionUID = 5706369770419859939L;
    
    private static Log log = LogFactory.getLog(PayInAction.class);

    /**
     * 
     * <pre>
     * 進件
     * 1、上傳圖片
     * 1.讀文件流數據
     * 2.寫數據到本地磁盤(即保存文件到本地服務器)
     * 3.文件存放路徑
     * 
     * 2、進件
     * </pre>
     * @author gzh
     * @date 2017年12月21日下午12:03:43
     */
    public void doIntoPiece() {
        
        String savePath = getServletContext().getRealPath("/photo/intoPiece"); // 獲得上傳文件的保存目錄,將上傳的文件存放於WEB-INF目錄下,不容許外界直接訪問,保證上傳文件的安全
        String tempPath = getServletContext().getRealPath("/photo/intoPieceTemp");         // 上傳時生成的臨時文件保存目錄
        File tmpFile = new File(tempPath);
        if (!tmpFile.exists()) {
            tmpFile.mkdir();
        }
        
        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(1024 * 100);
            factory.setRepository(tmpFile);
            ServletFileUpload upload = new ServletFileUpload(factory);
//            upload.setProgressListener(new ProgressListener() {
//                public void update(long pBytesRead, long pContentLength,
//                        int arg2) {
//                    System.out.println("文件大小爲:" + pContentLength + ",當前已處理:"
//                            + pBytesRead);
//                    /**
//                     * 文件大小爲:14608,當前已處理:4096 文件大小爲:14608,當前已處理:7367
//                     * 文件大小爲:14608,當前已處理:11419 文件大小爲:14608,當前已處理:14608
//                     */
//                    float f = pBytesRead / pContentLength;
//                    try {
//                        getHttpResponse().getWriter().write(f + "");
//                    } catch (IOException e) {
//                        // Auto-generated catch block
//                        e.printStackTrace();
//                    }
//
//                }
//            });
            upload.setHeaderEncoding("UTF-8");

            if (!ServletFileUpload.isMultipartContent(getHttpRequest())) {  // 判斷提交上來的數據是不是上傳表單的數據
                return;
            }

            upload.setFileSizeMax(1024 * 1024 * 5);
            upload.setSizeMax(1024 * 1024 * 5 * 5);
            List<FileItem> list = upload.parseRequest(getHttpRequest());
            for (FileItem item : list) {
                if (item.isFormField()) { // 若是fileitem中封裝的是普通輸入項的數據
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    log.info(name + "=" + value);
                } else { // 若是fileitem中封裝的是上傳文件
                    String filename = item.getName();
                    if (filename == null || filename.trim().equals("")) {
                        continue;
                    }
                    // 注意:不一樣的瀏覽器提交的文件名是不同的,有些瀏覽器提交上來的文件名是帶有路徑的,如:
                    // c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt
                    // 處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分
                    filename = filename
                            .substring(filename.lastIndexOf("\\") + 1);
                    String fileExtName = filename.substring(filename
                            .lastIndexOf(".") + 1); // 獲得上傳文件的擴展名
                    log.info("上傳的文件的擴展名是:" + fileExtName); // 若是須要限制上傳的文件類型,那麼能夠經過文件的擴展名來判斷上傳的文件類型是否合法
                    //讀文件流數據
                    InputStream in = item.getInputStream(); // 獲取item中的上傳文件的輸入流
                    String saveFilename = makeFileName(filename);                     // 獲得文件保存的名稱        
                    String realSavePath = makePath(saveFilename, savePath); // 獲得文件的保存目錄
                    log.info(realSavePath);
                    
                    FileOutputStream out = new FileOutputStream(realSavePath
                            + "\\" + saveFilename); // 建立一個文件輸出流
                    byte buffer[] = new byte[1024];    
                    int len = 0; // 判斷輸入流中的數據是否已經讀完的標識
                    while ((len = in.read(buffer)) > 0) { // 循環將輸入流讀入到緩衝區當中,(len=in.read(buffer))>0就表示in裏面還有數據
                        //寫數據到本地磁盤
                        out.write(buffer, 0, len); // 使用FileOutputStream輸出流將緩衝區的數據寫入到指定的目錄(savePath + "\\"+ filename)當中
                    }
                    
                    in.close();        
                    out.close();
                    item.delete();
                }
            }
            
            // TODO 進件
            
        } catch (FileUploadBase.FileSizeLimitExceededException e) {
            e.printStackTrace();
            return;
        } catch (FileUploadBase.SizeLimitExceededException e) {
            e.printStackTrace();
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Method: makeFileName
     * @Description: 生成上傳文件的文件名,文件名以:uuid+"_"+文件的原始名稱
     * @Anthor:孤傲蒼狼
     * @param filename
     *            文件的原始名稱
     * @return uuid+"_"+文件的原始名稱
     */
    private String makeFileName(String filename) { // 2.jpg
        // 爲防止文件覆蓋的現象發生,要爲上傳文件產生一個惟一的文件名
        return UUID.randomUUID().toString() + "_" + filename;
    }

    /**
     * 爲防止一個目錄下面出現太多文件,要使用hash算法打散存儲
     * 
     * @Method: makePath
     * @Description:
     * @Anthor:孤傲蒼狼
     * 
     * @param filename
     *            文件名,要根據文件名生成存儲目錄
     * @param savePath
     *            文件存儲路徑
     * @return 新的存儲目錄
     */
    private String makePath(String filename, String savePath) {
        // 獲得文件名的hashCode的值,獲得的就是filename這個字符串對象在內存中的地址
        int hashcode = filename.hashCode();
        int dir1 = hashcode & 0xf; // 0--15
        int dir2 = (hashcode & 0xf0) >> 4; // 0-15
        // 構造新的保存目錄
        String dir = savePath + "\\" + dir1 + "\\" + dir2; // upload\2\3
                                                            // upload\3\5
        // File既能夠表明文件也能夠表明目錄
        File file = new File(dir);
        // 若是目錄不存在
        if (!file.exists()) {
            // 建立目錄
            file.mkdirs();
        }
        return dir;
    }
}

參考

http://www.cnblogs.com/greatv...

相關文章
相關標籤/搜索