@@ -45,13 +45,25 @@ const METADATA_ATTR_KEYS = {
45
45
export class FileBackend implements StorageBackendAdapter {
46
46
client = null
47
47
filePath : string
48
+ etagAlgorithm : 'mtime' | 'md5'
48
49
49
50
constructor ( ) {
50
- const { storageFilePath } = getConfig ( )
51
+ const { storageFilePath, storageFileEtagAlgorithm } = getConfig ( )
51
52
if ( ! storageFilePath ) {
52
53
throw new Error ( 'FILE_STORAGE_BACKEND_PATH env variable not set' )
53
54
}
54
55
this . filePath = storageFilePath
56
+ this . etagAlgorithm = storageFileEtagAlgorithm
57
+ }
58
+
59
+ private async etag ( file : string , stats : fs . Stats ) : Promise < string > {
60
+ if ( this . etagAlgorithm === 'md5' ) {
61
+ const checksum = await fileChecksum ( file )
62
+ return `"${ checksum } "`
63
+ } else if ( this . etagAlgorithm === 'mtime' ) {
64
+ return `"${ stats . mtimeMs . toString ( 16 ) } -${ stats . size . toString ( 16 ) } "`
65
+ }
66
+ throw new Error ( 'FILE_STORAGE_ETAG_ALGORITHM env variable must be either "mtime" or "md5"' )
55
67
}
56
68
57
69
/**
@@ -70,7 +82,7 @@ export class FileBackend implements StorageBackendAdapter {
70
82
// 'Range: bytes=#######-######
71
83
const file = path . resolve ( this . filePath , withOptionalVersion ( `${ bucketName } /${ key } ` , version ) )
72
84
const data = await fs . stat ( file )
73
- const checksum = await fileChecksum ( file )
85
+ const eTag = await this . etag ( file , data )
74
86
const fileSize = data . size
75
87
const { cacheControl, contentType } = await this . getFileMetadata ( file )
76
88
const lastModified = new Date ( 0 )
@@ -92,7 +104,7 @@ export class FileBackend implements StorageBackendAdapter {
92
104
contentRange : `bytes ${ startRange } -${ endRange } /${ fileSize } ` ,
93
105
httpStatusCode : 206 ,
94
106
size : size ,
95
- eTag : checksum ,
107
+ eTag,
96
108
contentLength : chunkSize ,
97
109
} ,
98
110
httpStatusCode : 206 ,
@@ -107,7 +119,7 @@ export class FileBackend implements StorageBackendAdapter {
107
119
lastModified : lastModified ,
108
120
httpStatusCode : 200 ,
109
121
size : data . size ,
110
- eTag : checksum ,
122
+ eTag,
111
123
contentLength : fileSize ,
112
124
} ,
113
125
body,
@@ -205,12 +217,12 @@ export class FileBackend implements StorageBackendAdapter {
205
217
await this . setFileMetadata ( destFile , Object . assign ( { } , originalMetadata , metadata ) )
206
218
207
219
const fileStat = await fs . lstat ( destFile )
208
- const checksum = await fileChecksum ( destFile )
220
+ const eTag = await this . etag ( destFile , fileStat )
209
221
210
222
return {
211
223
httpStatusCode : 200 ,
212
224
lastModified : fileStat . mtime ,
213
- eTag : checksum ,
225
+ eTag,
214
226
}
215
227
}
216
228
@@ -252,15 +264,14 @@ export class FileBackend implements StorageBackendAdapter {
252
264
const { cacheControl, contentType } = await this . getFileMetadata ( file )
253
265
const lastModified = new Date ( 0 )
254
266
lastModified . setUTCMilliseconds ( data . mtimeMs )
255
-
256
- const checksum = await fileChecksum ( file )
267
+ const eTag = await this . etag ( file , data )
257
268
258
269
return {
259
270
httpStatusCode : 200 ,
260
271
size : data . size ,
261
272
cacheControl : cacheControl || 'no-cache' ,
262
273
mimetype : contentType || 'application/octet-stream' ,
263
- eTag : `" ${ checksum } "` ,
274
+ eTag,
264
275
lastModified : data . birthtime ,
265
276
contentLength : data . size ,
266
277
}
0 commit comments