Propogate last modified time
It should've also been possible to use the regular Last-Modified HTTP header, however that'd have caused a potential loss of precsion if I correctly understand the string format that we'll need to use. Refs: - https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toUTCString - https://nodejs.org/api/fs.html#class-fsstats
This commit is contained in:
parent
e8e53b2ca5
commit
f5ef478a90
4 changed files with 45 additions and 31 deletions
|
@ -62,9 +62,15 @@ const handleRead = async (path: string) => {
|
|||
// this is binary data.
|
||||
res.headers.set("Content-Type", "application/octet-stream");
|
||||
|
||||
const stat = await fs.stat(path);
|
||||
|
||||
// Add the file's size as the Content-Length header.
|
||||
const fileSize = (await fs.stat(path)).size;
|
||||
const fileSize = stat.size;
|
||||
res.headers.set("Content-Length", `${fileSize}`);
|
||||
|
||||
// Add the file's last modified time (as epoch milliseconds).
|
||||
const mtimeMs = stat.mtimeMs;
|
||||
res.headers.set("X-Last-Modified-Ms", `${mtimeMs}`);
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
|
|
|
@ -34,7 +34,7 @@ type RawEXIFData = Record<string, any> &
|
|||
ImageHeight: number;
|
||||
}>;
|
||||
|
||||
const EXIF_TAGS_NEEDED = [
|
||||
const exifTagsNeededForParsingImageMetadata = [
|
||||
"DateTimeOriginal",
|
||||
"CreateDate",
|
||||
"ModifyDate",
|
||||
|
@ -53,31 +53,19 @@ const EXIF_TAGS_NEEDED = [
|
|||
];
|
||||
|
||||
/**
|
||||
* Read EXIF data from an image and use that to construct and return an
|
||||
* {@link ParsedExtractedMetadata}. This function is tailored for use when we
|
||||
* upload files.
|
||||
* Read EXIF data from an image {@link file} and use that to construct and
|
||||
* return an {@link ParsedExtractedMetadata}.
|
||||
*
|
||||
* @param fileOrData The image {@link File}, or its contents.
|
||||
* This function is tailored for use when we upload files.
|
||||
*/
|
||||
export const parseImageMetadata = async (
|
||||
fileOrData: File | Uint8Array,
|
||||
file: File,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
): Promise<ParsedExtractedMetadata> => {
|
||||
/*
|
||||
if (!(receivedFile instanceof File)) {
|
||||
receivedFile = new File(
|
||||
[await receivedFile.blob()],
|
||||
receivedFile.name,
|
||||
{
|
||||
lastModified: receivedFile.lastModified,
|
||||
},
|
||||
);
|
||||
}
|
||||
*/
|
||||
const exifData = await getParsedExifData(
|
||||
fileOrData,
|
||||
file,
|
||||
fileTypeInfo,
|
||||
EXIF_TAGS_NEEDED,
|
||||
exifTagsNeededForParsingImageMetadata,
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -375,21 +375,32 @@ export const assetName = ({
|
|||
*/
|
||||
const readFileOrPath = async (
|
||||
fileOrPath: File | string,
|
||||
): Promise<{ dataOrStream: Uint8Array | DataStream; fileSize: number }> => {
|
||||
): Promise<{
|
||||
dataOrStream: Uint8Array | DataStream;
|
||||
fileSize: number;
|
||||
lastModifiedMs: number;
|
||||
}> => {
|
||||
let dataOrStream: Uint8Array | DataStream;
|
||||
let fileSize: number;
|
||||
let lastModifiedMs: number;
|
||||
|
||||
if (fileOrPath instanceof File) {
|
||||
const file = fileOrPath;
|
||||
fileSize = file.size;
|
||||
lastModifiedMs = file.lastModified;
|
||||
dataOrStream =
|
||||
fileSize > MULTIPART_PART_SIZE
|
||||
? getFileStream(file, FILE_READER_CHUNK_SIZE)
|
||||
: new Uint8Array(await file.arrayBuffer());
|
||||
} else {
|
||||
const path = fileOrPath;
|
||||
const { response, size } = await readStream(ensureElectron(), path);
|
||||
const {
|
||||
response,
|
||||
size,
|
||||
lastModifiedMs: lm,
|
||||
} = await readStream(ensureElectron(), path);
|
||||
fileSize = size;
|
||||
lastModifiedMs = lm;
|
||||
if (size > MULTIPART_PART_SIZE) {
|
||||
const chunkCount = Math.ceil(size / FILE_READER_CHUNK_SIZE);
|
||||
dataOrStream = { stream: response.body, chunkCount };
|
||||
|
@ -398,7 +409,7 @@ const readFileOrPath = async (
|
|||
}
|
||||
}
|
||||
|
||||
return { dataOrStream, fileSize };
|
||||
return { dataOrStream, fileSize, lastModifiedMs };
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,18 +19,21 @@ import type { Electron } from "@/next/types/ipc";
|
|||
* @param path The path on the file on the user's local filesystem whose
|
||||
* contents we want to stream.
|
||||
*
|
||||
* @return A ({@link Response}, size) tuple.
|
||||
* @return A ({@link Response}, size, lastModifiedMs) triple.
|
||||
*
|
||||
* * The response contains the contents of the file. In particular, the `body`
|
||||
* {@link ReadableStream} property of this response can be used to read the
|
||||
* files contents in a streaming manner.
|
||||
*
|
||||
* * The size is the size of the file that we'll be reading from disk.
|
||||
*
|
||||
* * The lastModifiedMs value is the last modified time of the file that we're
|
||||
* reading, expressed as epoch milliseconds.
|
||||
*/
|
||||
export const readStream = async (
|
||||
_: Electron,
|
||||
path: string,
|
||||
): Promise<{ response: Response; size: number }> => {
|
||||
): Promise<{ response: Response; size: number; lastModifiedMs: number }> => {
|
||||
const req = new Request(`stream://read${path}`, {
|
||||
method: "GET",
|
||||
});
|
||||
|
@ -41,13 +44,19 @@ export const readStream = async (
|
|||
`Failed to read stream from ${path}: HTTP ${res.status}`,
|
||||
);
|
||||
|
||||
const size = +res.headers["Content-Length"];
|
||||
if (isNaN(size))
|
||||
throw new Error(
|
||||
`Got a numeric Content-Length when reading a stream. The response was ${res}`,
|
||||
);
|
||||
const size = readNumericHeader(res, "Content-Length");
|
||||
const lastModifiedMs = readNumericHeader(res, "X-Last-Modified-Ms");
|
||||
|
||||
return { response: res, size };
|
||||
return { response: res, size, lastModifiedMs };
|
||||
};
|
||||
|
||||
const readNumericHeader = (res: Response, key: string) => {
|
||||
const value = +res.headers[key];
|
||||
if (isNaN(value))
|
||||
throw new Error(
|
||||
`Expected a numeric ${key} when reading a stream response: ${res}`,
|
||||
);
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue