(十二)springMvc 處理圖片,視頻等文件的上傳

導包

須要導入以下的包html

commons-fileupload-1.3.3.jar
commons-io-2.6.jar
java


修改表單類型

想要上傳圖片、文本、電影、音樂等資源的時候,須要將 form 的類型改成 multipart/form-dataweb

<form enctype="multipart/form-data">

配置解析器

springMvc.xml 文件中進行配置 ;算法

<!--配置圖片、音樂等文件的解析器-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--限制上文最大爲5M 1024*1024*5-->
        <property name="maxInMemorySize">
            <value>5242880 </value>
        </property>
    </bean>

處理上傳的圖片

springMvc 對這類型的數據,也支持 參數綁定 ,使用 MultipartFile 接收 ,注意頁面上的 name 屬性的值和形參名一致,老生常談的事了;spring

MultipartFile 的一些基本操做 :json

// 獲取上傳的文件名
       String oldFile = multipartFile.getOriginalFilename() ;
// 將上傳的文件,從內存中寫到硬盤上
       multipartFile.transferTo(path);

補充一個本身寫的工具類

以前寫的過於簡單,補充下一個實例;
  1. 上傳文件瀏覽器

    先判斷 HttpServletRequest 是不是 MultipartHttpServletRequest 的實例,若是不是,則表示 HttpServletRequest 只是一個普通的 request ,並無帶文件過來,固然網上還有其餘好幾種判斷方法,這是我經常使用的一種;markdown

    public String upLoadExcel(HttpServletRequest request) {
            JSONObject jsonObject = new JSONObject();
            if (!(request instanceof MultipartHttpServletRequest)) {
                jsonObject.put("result", "0");
                jsonObject.put("resultInfo", "沒有選中任何文件");
                return jsonObject.toJSONString();
            }
            ...
     }

    若是HttpServletRequestMultipartHttpServletRequest 的實例,則進行強轉,將 HttpServletRequest 轉成 MultipartHttpServletRequest 的實例;而後獲取上傳的文件:app

    首先說明下,上傳的文件的狀況,它是一個 Map 中套 List 的狀況。框架

    所以,獲取文件,須要先獲取外層的 MapMultipartHttpServletRequest提供了獲取其迭代器的方法:

    Iterator<String> iterator = request.getFileNames();

    這樣就獲取了全部的文件名,注意下 Map 裏面套的是 List 所以,這些名字就是 Map 的鍵,一個鍵對應一個值 List ,就是說一個文件名能夠對應多個文件。

    根據文件名獲取其對應的 List :

    List<MultipartFile> files = request.getFiles(fileName);

    這樣就獲取到了一個文件對應的 Lsit 集合,再迭代這個 List 就能夠獲取其對應的文件。


    下面是一個實例:

    /** * 文件上傳 * <p> * 先遍歷名字,在根據名字遍歷對應的文件,兩層循環,ok! * * @param request 接受提交文件的 request * @return 返回上傳的文件的保存路徑 */
        public static List<String> fileUpload(MultipartHttpServletRequest request) throws IOException {
            List<String> paths = new ArrayList<>();
            // String path = FileUpDownloadUtils.class.getClassLoader().getResource("UpDownLoad" + File.separator + "readme.txt").getPath();
            // 當前web應用的絕對路徑
            // String path = request.getSession().getServletContext().getRealPath("/") + "UpDownLoad";
            // 獲取系統的路徑
            String path = File.separator + "UpDownLoad";
            Iterator<String> iterator = request.getFileNames();
    
            while (iterator.hasNext()) {
                String fileName = iterator.next();
                List<MultipartFile> files = request.getFiles(fileName);
                if (files.size() > 0) {
                    ListIterator<MultipartFile> multipartFileListIterator = files.listIterator();
                    while (multipartFileListIterator.hasNext()) {
                        String uuid = UUID.randomUUID().toString();
                        String path_in = getPathByHashcode(path, uuid);
                        MultipartFile multipartFile = multipartFileListIterator.next();
                        StringBuilder builder = new StringBuilder();
                        builder.append(path_in + File.separator);
                        builder.append(uuid + "_");
                        builder.append(multipartFile.getOriginalFilename());
                        File file = new File(builder.toString());
                        paths.add(file.getAbsolutePath());
                        multipartFile.transferTo(file);
                    }
                }
            }
            return paths;
        }

    再附送下代碼中,我寫的文件隨機分配算法,這是其中的一種實現,只適合代碼去讀文件,人工找某個文件比較費勁,還有一種實現是按照日期分配;

    日期分配,方便人工去拿文件,可是存在弱點,若是一天以內,有人暴力上傳文件,文件夾就會被撐爆。各有各的優缺點。

    /** * 文件分配算法,根據UUid的值 算出文件保存的地址 ; * <p> * UUID 的長度是固定的,而後根據其長度,保證其生成的 hascode 的長度也是同樣長的(32位) ; * <p> * 每四位取爲一個int 值 ,最多能夠取 8 層 ; * <p> * 能夠保存 16 * 16 * 16 * 16 * 1000 = 4 096 000(四百萬份合同) ; * * @param path * @param uuid * @return */
    private static String getPathByHashcode(String path, String uuid) {
        int hashcode = uuid.hashCode();
        int one = hashcode & 0xf;
        int two = (hashcode >> 4) & 0xf;
        int three = (hashcode >> 4 >> 4) & 0xf;
        int four = (hashcode >> 4 >> 4 >> 4) & 0xf;
    
        File file = new File(path +
                File.separator + one + File.separator + two
                + File.separator + three + File.separator + four);
    
        if (!file.exists()) {
            file.mkdirs();
        }
    
        return file.getPath();
    }
  2. 下載文件

    導包都是導入 spring 框架下面的,不要導錯了。作了下載文件的時候,對文件名的兼容性,能夠有空格。

    /** * springMvc 的下載,原始的response的outputStream 怎麼用的,都要忘記了 見鬼的框架,真香的封裝 * * @param imgPaths 封裝須要下載的文件的路徑 * @return */
        public static ResponseEntity<Resource> fileDownload(String imgPaths, int blag) throws UnsupportedEncodingException {
    
            File file = new File(imgPaths);
            String simpleName = imgPaths.substring(imgPaths.indexOf("_") + 1);
    
            Resource body = new FileSystemResource(file);
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();
    
            HttpStatus status = HttpStatus.CREATED;
    
            /** * 對文件名進行處理下 */
            // 瀏覽器分爲 火狐 和 非火狐
            if (request.getHeader("USER-AGENT").toLowerCase().indexOf("firefox") >= 0) {
                // 火狐頭大,須要獨特設置一下
                simpleName = new String(simpleName.getBytes("UTF-8"), "iso-8859-1");
            } else {
                simpleName = URLEncoder.encode(simpleName, "UTF-8");
                // IE 文件名有空格會被加號代替。須要本身替換回去
                simpleName = simpleName.replaceAll("\\+", "%20");
            }
    
    
            String suffix = simpleName.substring(simpleName.lastIndexOf(".") + 1);
            HttpHeaders headers = new HttpHeaders();
            switch (blag) {
                /** * 內嵌顯示,針對IE瀏覽器:TEXT_PLAIN * 文件名有空格。火狐則會截斷文件名,須要將文件名用字符串包起來.使用 springMvc 再也不須要這樣作,而且你作了,還會在文件名先後各加一個 _ ; * * 預覽須要本身判斷下文件類型。 * */
                case SHOW:
                    MediaType mediaType;
                    switch (suffix.toLowerCase()) {
                        case "png":
                        case "jpg":
                        case "gif":
                            mediaType = MediaType.TEXT_PLAIN;
                            break;
                        // case "html":
                        // case "xml":
                        // case "markdown":
                        // mediaType = MediaType.valueOf("text/" + suffix);
                        // break;
                        default:
                            mediaType = MediaType.valueOf("application/" + suffix);
    
                    }
                    headers.setContentType(mediaType);
                    break;
                /** * 下載,下載設置內容格式爲二進制數據:MediaType.APPLICATION_OCTET_STREAM */
                case DOWNLOAD:
                    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                    headers.setContentDispositionFormData("attachment", simpleName);
                    break;
            }
    
            headers.setContentLength(file.length());
            return new ResponseEntity<>(body, headers, status);
        }

    其中的常量是:

    傳入 0 ,就只是顯示在瀏覽器上,不下載,這個只顯示功能還有點問題,圖片、pdf等格式會顯示,一些其餘格式不管怎麼調試都是會下載。。。 ; 1 是下載。

    public static final int SHOW = 0;
      public static final int DOWNLOAD = 1;
相關文章
相關標籤/搜索