檔案上傳採用虛擬路徑實現項目部署和使用者資源分離,檔案上傳部署
實現使用者資源和項目分離使用到了下面這個工具類:
儲存路徑工具類
package cn.gukeer.common.utils;import com.github.pagehelper.StringUtil;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.core.io.ClassPathResource;import org.springframework.web.multipart.MultipartFile;import java.io.*;import java.util.Properties;import java.util.StringTokenizer;/** * 檔案管理協助類,處理應用之外的檔案,如照片、郵件附件等不依賴於應用存在而存在的檔案。 注意:裡面的檔案路徑除了特殊說明外都是基於VFS根路徑的 * * @author guowei */public abstract class VFSUtil { private static Log log = LogFactory.getLog(VFSUtil.class); /** * VFS 根路徑(最後沒有/號) */ private static String VFS_ROOT_PATH; static { try { readVFSRootPath();// 給VFS_ROOT_PATH賦初始值 } catch (Exception e) { log.error("讀取設定檔出錯!", e); } } /** * 讀取VFS路徑設定檔 */ private static void readVFSRootPath() { String key = null; if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) { key = "vfsroot.windows"; } else { key = "vfsroot.linux"; } try { Properties p = new Properties(); InputStream inStream = new ClassPathResource("/db.properties").getInputStream(); p.load(inStream); VFS_ROOT_PATH = p.getProperty(key); } catch (Exception e1) { VFS_ROOT_PATH = ""; log.error("[vfsroot路徑讀取]設定檔模式出錯!", e1); } if (StringUtil.isEmpty(VFS_ROOT_PATH)) { if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) { VFS_ROOT_PATH = "C:/gukeer/vfsroot/"; } else { VFS_ROOT_PATH = "/opt/gukeer/vfsroot/"; } } } /** * 擷取當前的VfsRootPath * * @return */ public static String getVFSRootPath() { return VFS_ROOT_PATH; } /** * 擷取檔案輸入資料流 * * @param file * @param fileStream * @return */ public static InputStream getInputStream(File file, boolean fileStream) { if (fileStream == true) {//使用檔案流 FileInputStream fin = null; try { fin = new FileInputStream(file); } catch (FileNotFoundException e) { if (log.isDebugEnabled()) { log.debug(e); } String msg = "找不到指定的檔案[" + file.getName() + "]。"; if (log.isDebugEnabled()) { log.debug(msg); } throw new FileOperationException(msg, e); } return fin; } else { // 使用記憶體流 InputStream in = null; if (file != null && file.canRead() && file.isFile()) { try { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); FileInputStream stream = new FileInputStream(file); BufferedInputStream bin = new BufferedInputStream(stream); int len = 0; byte[] b = new byte[1024]; while ((len = bin.read(b)) != -1) { buffer.write(b, 0, len); } stream.close(); in = new ByteArrayInputStream(buffer.toByteArray()); } catch (Exception e) { String msg = "不能讀取檔案[" + file.getName() + "]"; if (log.isErrorEnabled()) { log.error(msg, e); } throw new FileOperationException(msg, e); } } else { String msg = "不是檔案或檔案不可讀[" + file.getName() + "]"; if (log.isDebugEnabled()) { log.debug(msg); } throw new FileOperationException("不是檔案或檔案不可讀"); } return in; } }}
注意事項:
①在resources檔案夾內配置properties檔案,包含vfsroot路徑資訊(windows和linux兩個路徑),修改上傳方法使使用者上傳的檔案和其他資源均儲存在vfsroot路徑下,並將圖片儲存路徑儲存在資料庫內方便用戶端讀取使用; properties配置demo:
#db configjdbc.schema=gk_platformjdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=falsejdbc.username=rootjdbc.password=123456vfsroot.windows=C:/platform/vfsroot/vfsroot.linux=/opt/platform/vfsroot/
②由於用戶端不能直接請求訪問位於伺服器實體路徑上的資源,因此前端頁面採用流讀取的方式顯示圖片和其他資源;在controller內添加如下方法:
/** * 讀取圖片檔案 * * @param response * @throws Exception */ @RequestMapping("/website/showPicture") public void showPicture(HttpServletResponse response, String picPath) throws Exception { File file = new File(VFS_ROOT_PATH + picPath); if (!file.exists()) { logger.error("找不到檔案[" + VFS_ROOT_PATH + picPath + "]"); return; } response.setContentType("multipart/form-data"); InputStream reader = null; try { reader = VFSUtil.getInputStream(file, true); byte[] buf = new byte[1024]; int len = 0; OutputStream out = response.getOutputStream(); while ((len = reader.read(buf)) != -1) { out.write(buf, 0, len); } out.flush(); } catch (Exception ex) { logger.error("顯示圖片時發生錯誤:" + ex.getMessage(), ex); } finally { if (reader != null) { try { reader.close(); } catch (Exception ex) { logger.error("關閉檔案流出錯", ex); } } } }
前台jsp頁面調用:<img src="<%=contextPath%>${image.imagesUrl}">,例如:
<img src='test/website/showPicture?picPath=/images/upload/image/20160608/1465355183063.png'/>
資料庫儲存圖片的URL為/website/showPicture?picPath=/images/upload/image/20160608/1465355183063.png