問題: 開發web應用的過程中,我們通常會有文件上傳的需求,一般由客戶端上傳到伺服器上的文件不會被保存到資料庫中(這樣會產生一定的安全性問題),而是將上傳的文件保存到伺服器上的一個特定的目錄中.如果單單將所有的文件都保存到一個目錄中,也會產生一些問題,當網站訪問量很大,上傳文件很多時,伺服器上保存文 ...
問題:
開發web應用的過程中,我們通常會有文件上傳的需求,一般由客戶端上傳到伺服器上的文件不會被保存到資料庫中(這樣會產生一定的安全性問題),而是將上傳的文件保存到伺服器上的一個特定的目錄中.如果單單將所有的文件都保存到一個目錄中,也會產生一些問題,當網站訪問量很大,上傳文件很多時,伺服器上保存文件的目錄會由於保存太多的文件,而產生打開和讀寫都很緩慢的問題.解決這個問題的思路就是對上傳的文件按照一定的規則,保存到不同的目錄中.
解決方案:
思路一:可以按照上傳的時間將文件保存到不同的目錄中,如2018年1月份上傳的文件,保存到 /2018/1 目錄中.當然根據網站的流量,這樣的目錄層次還可以繼續劃分下去.
代碼實現:
/** * 目錄規則:/yyyy/MM/dd * 按時間生成上傳文件的存儲路徑的思路簡單,而且一般的web應用使用這種方式也可以滿足需求. * 如果網站訪問量很大,上傳文件很多時,還可以繼續往下分:/yyyy/MM/dd/hh/mm.. * */ public static String getPathByTime() { StringBuilder path = new StringBuilder(); // 按系統當前時間計算出存儲路徑 Calendar currTime = Calendar.getInstance(); int year = currTime.get(Calendar.YEAR); int month = currTime.get(Calendar.MONTH) + 1; int day = currTime.get(Calendar.DAY_OF_MONTH); // 字元串拼接 path.append(File.separator + year).append(File.separator + month).append(File.separator + day); return path.toString(); }
思路二:目錄分離演算法,其實就是一個小技巧,使用它可以得到一個目錄結構,這個目錄結構可以保證每個目錄中的文件數量不會太多.
步驟1.給定一個唯一的文件名,獲取這個文件名的哈希碼值 code.
步驟2.code 值是一個整數,我們將 code 和 0xf 相與,得到一個 int 值作為第一層目錄名(思考一下,這個 int 值的範圍,就是0-15).
步驟3.然後將 code 值無符號右移4位,得到一個新的 int 值賦予 code,然後將 code 再和 0xf 相與,得到第二層目錄名.
因為 Java 中一個整數占4個位元組,也就是32位,那麼一個整數按照上述規則,最多右移8次就會歸0.所以我們可以將上述過程進行8次,得到8級目錄,由於每次右移4位,所以每級目錄中最多有16個子目錄(0-15).好啦,我只能表述到這裡啦.直接看看代碼吧.
代碼實現:
/** * 目錄分離演算法:由此演算法可以得到8級目錄,每一級目錄中最多有16個子目錄,所以此演算法最大可計算出42.9億多個存儲路徑. * 由唯一文件名計算出一個存儲路徑,可以有效避免在一個目錄中存儲太多的文件. * */ public static String getPath(String name) { int hash = name.hashCode(); StringBuilder path = new StringBuilder(); for (int i=0; i<8; i++) { // hash & 0xf 後,得到0-15中的一個整數 int dir = hash & 0xf; // 將 hash 碼無符號右移 4 位(一個整數最多右移8次就歸0) hash = hash >>> 4; // 字元串拼接 path.append(File.separator + dir); } return path.toString(); }
總結:當然了,這樣的目錄劃分還有很多其它的規則,根據不同的需求,我們可以選擇適合自己的方案.至於上述的方案,第一種簡單直接,符合人類思維方式,上傳的文件組織的很有規律,比較方便整理;第二種則更加符合電腦思維,對於上傳量很大,又沒有什麼必要管理的應用,也是很好的選擇.