1. 程式人生 > >遇到問題-----uploadify上傳檔案ServletFileUpload.isMultipartContent(request)為false

遇到問題-----uploadify上傳檔案ServletFileUpload.isMultipartContent(request)為false

現象和問題

我們使用的是SpirngMVC框架,然後在其中使用uploadify上傳檔案。

上傳程式碼為:

      //初始化圖片上傳容器
        var initImageUploader = function () {
            var selfId = $('#icon_upload_uploader').attr("id");
            var $input = $('#icon_upload_filePath');
            console.log($input);
            $('#icon_upload_uploader').uploadifive({
                'height': 300,
                'width': 300,
                'uploadScript': '/upload;_sid=${pageContext.session.id}',
                'fileSizeLimit': '1200KB',
                'buttonClass': 'upload-image img-thumbnail',
                'buttonText': '',
                'multi': false,
                'onInit': function(instance) {
                    updateUploadButtonBackground(selfId, $input.val());
                },
                'removeCompleted': true,
                'onUploadComplete': function (file, data, response) {
                    data = JSON.parse(data);
                    if (data.code) {
                        var url = '${hostname}' + data.result;
                        $input.val(url);
                        updateUploadButtonBackground(selfId, url);
                    }
                }
            });
        };
        initImageUploader();


接收程式碼為:

package com.test.web.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.test.util.AjaxResult;

/**
 * 通用的上傳(儲存到本地伺服器)
 * 
 */
@Controller
public class UploadController {

    private final Logger logger = LoggerFactory.getLogger(getClass().getName());

    /**
     * 上傳到伺服器,檔名稱隨機生成(基本可以保證不重複)
     * 
     * @param request
     * @param response
     * @return AjaxResult 儲存的檔案的相對路徑
     * @throws IOException 
     */
    @RequestMapping("/upload")
    @ResponseBody
    public AjaxResult upload(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
        	
        	//獲取檔案儲存路徑  
            String path = request.getRealPath("/upload"); 
        	
            String fileNameResult ="";
            // 判斷enctype屬性是否為multipart/form-data  
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
            if (!isMultipart)  
                throw new IllegalArgumentException(  
                        "上傳內容不是有效的multipart/form-data型別.");  
      
            // Create a factory for disk-based file items  
            DiskFileItemFactory factory = new DiskFileItemFactory();  
      
            // Create a new file upload handler  
            ServletFileUpload upload = new ServletFileUpload(factory);  
            // Parse the request  
            List<?> items = upload.parseRequest(request);  
      
            Iterator iter = items.iterator();  
            while (iter.hasNext()) {  
                FileItem item = (FileItem) iter.next();  
      
                if (item.isFormField()) {  
                    // 如果是普通表單欄位  
                    String name = item.getFieldName();  
                    String value = item.getString();  
                    // ...  
                } else {  
                    // 如果是檔案欄位  
                    String fieldName = item.getFieldName();  
                    String fileName = item.getName();  
                    String contentType = item.getContentType();  
                    boolean isInMemory = item.isInMemory();  
                    long sizeInBytes = item.getSize();  
                    String fileExt = fileName.substring(fileName.lastIndexOf('.'));
                    String fileNameNew =getFileNameNew()+fileExt;
                    fileNameResult=fileNameNew;
                    //儲存到本地
                        InputStream uploadedStream = item.getInputStream();  
                        savePic(path,uploadedStream,fileNameNew);
                        uploadedStream.close();  
                }  
            }  
            
            return AjaxResult.resultSuccess("/upload/"+fileNameResult);
        } catch (FileUploadException e) {
            logger.warn(e.getMessage(), e);
            return AjaxResult.resultError(e.getMessage());
        }
    }
    
    private void savePic(String path,InputStream inputStream, String fileName) {
    	 
        OutputStream os = null;
        try {
          // 2、儲存到臨時檔案
          // 1K的資料緩衝
          byte[] bs = new byte[1024];
          // 讀取到的資料長度
          int len;
          // 輸出的檔案流儲存到本地檔案
     
          File tempFile = new File(path);
          if (!tempFile.exists()) {
            tempFile.mkdirs();
          }
          os = new FileOutputStream(tempFile.getPath() + File.separator + fileName);
          // 開始讀取
          while ((len = inputStream.read(bs)) != -1) {
            os.write(bs, 0, len);
          }
     
        } catch (IOException e) {
          e.printStackTrace();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          // 完畢,關閉所有連結
          try {
            os.close();
            inputStream.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }

    private String getFileNameNew() {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return fmt.format(new Date());
      }

}


遇到問題,第一次上傳圖片成功之後,第二次上傳圖片時 報錯 上傳內容不是有效的multipart/form-data型別。

也就是說ServletFileUpload.isMultipartContent(request)為false。

request中不含有檔案表單資料。

經過排查 發現原因是   寫入檔案時 建立的 路徑與路由路徑衝突導致的。

細心的讀者可以發現  uploadify中設定的 上傳到 路由的路徑為:

'uploadScript': '/upload;_sid=${pageContext.session.id}',

也就是

/upload

但是在儲存 圖片到 本地伺服器時 ,我們儲存的路徑也是/upload。

//獲取檔案儲存路徑  
            String path = request.getRealPath("/upload"); 

第一次上傳圖片時,會建立upload資料夾。

訪問圖片使用 http://127.0.0.1/upload/圖片名.png  訪問。

當第二次 圖片上傳時,有兩個 /upload 路由請求連結。

所以進到 接收檔案的路由  /upload 時,已經不是含有檔案的request了。

解決方法

儲存檔案的路徑不使用 與 路由同名路徑。 如果已經存在同名靜態資源訪問路徑,則需要刪除同名靜態資原始檔夾 或者 修改路由路徑。

例如 我這裡把 儲存圖片的地址修改為/uploadfile。