Contents

檔案下載一直抓到舊檔案的問題

遇到問題

最近用 .NET Core 做動態依照資料庫使用者會帶過來參數去尋找檔案路徑做回傳下載。下載檔案都是舊版本。我看Console 的 Network 都是 200。也沒有看到 204 抓Cache 的結果。這到底是為什麼呢?今天遇到我覺得要把這個問題找到。

這邊說這麼詳細是怕有各種情境有可能就會有不一樣結果。

簡單實驗

後來抓到檔案因為我們沒有設定Cache-Control,然後動態下載檔案他的Last-Modified當下時間可能是檔案異動時間。這邊雖然我沒給Last-Modified,是程式內部機制給的時間,雖然好像可以設定Last-Modified,但我發現再次跑檔案根本沒有進 Server 取檔案。仔細看Console 顯示200 磁碟快取,我覺得一定有什麼關係取到快取。雖然網路上很多交用Cache-Control: no-cachemax-age=xxx,但我覺得要了解為什麼比較重要。

這邊用小遊戲下載網隨便一個檔案來Demo
第一次跑
https://i.imgur.com/pdiOuOL.png
第二次跑
https://i.imgur.com/4TPK7GT.png

我找到這篇http - What happens if you don’t set cache-control header? - Webmasters Stack Exchange
裡面提到Chrome 至少 Cache 一個禮拜和(current time - last modified time) / 10兩者最小值。Firefox 規則又不太一樣。每一家實作不一樣,真的不好找阿…

我觀察Github Release 下載檔案做的事情,他下載是有做Cache-Control: no-cache,不過我視覺的能不能設定個60秒之類的會比不會比較好,減少 Server Loading。

https://i.imgur.com/pWtSXML.png

找到問題

沒有副檔名的時候不會發送If-Modified-Since。上面測小遊戲下載網隨便一個檔案來Demo的exe檔案,請求(Request)竟然不會帶到這個header If-Modified-Since 。不過我這邊放在hfs上面,發現能抓到cache。但把test7z(沒有副檔名)放在hfs下載,兩次下載都會吃到Cache。

所以我推知之前用程式指向路徑做下載,應該是採到 URL 沒有副檔名關係,所以都會吃到Cache。所以程式做這些事情可能要留意一下這個問題。

第一次
https://i.imgur.com/yQxykMJ.png

第二次
https://i.imgur.com/NhnjbDB.png

簡單說重點

我發現當沒有 Cache-Control 時候瀏覽器還是會做緩存,預設為(current time - last modified time) / 10,但這部分是找到相關資料,所以沒有什麼動作就會有緩存動作。這讓我想到以前做後端回傳報表資料都會有緩存問題,但有可能是這個問題。但這個緩存問題有時很複雜,有可能是 Server 吃住 Cache 導致,有可能要重啟服務才能跑。

解決方法

程式指向檔案最好加上Cache-Control: no-cachemax-age就好。這邊我選擇的是控制max-age。至少有一分鐘緩存,User一直狂點連結那一小時都是緩存的。

.Net Core

這邊留 .Net Core 解決方法。
ASP.NET Core 中的回應快取 | Microsoft Docs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
        [HttpGet]
        [ResponseCache(Duration = 60)]
        public IActionResult Get([FromQuery] RequestDto request)
        {
            string filePath = "/sss/ssss/ffff.mp4";

            if (string.IsNullOrEmpty(filePath))
            {
                return NotFound();
            }
            string fileName = Path.GetFileName(filePath);
            new FileExtensionContentTypeProvider().TryGetContentType(fileName, out string contentType);
            contentType ??= "application/octet-stream";
            return PhysicalFile(filePath, contentType, fileDownloadName: fileName, enableRangeProcessing: true);
        }

19.研究OutputCache、ResponseCache兩快取差異 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Spring Boot

Laravel

文章

緩存還有很多東西還沒,有分舊版和新版,甚至瀏覽器重新整理會帶的 Request也會不一樣。

https://user-images.githubusercontent.com/6058558/220018613-184bf6ab-510f-4cf3-aad8-2466399f0cee.png

其他參考

caching - What’s default value of cache-control? - Stack Overflow

彩蛋

金流自己串,使用 Node.js 串接 LINE Pay