fix: missing images causing download errors
This commit is contained in:
@@ -10,7 +10,7 @@ import { getExtensionForUrl } from '@/utility/mimeType';
|
||||
export const downloadAdapter = createEntityAdapter<DownloadEntity>();
|
||||
|
||||
export const queueTrackForDownload = createAction<string>('download/queue');
|
||||
export const initializeDownload = createAction<{ id: string, size?: number, jobId?: number, location: string, image: string }>('download/initialize');
|
||||
export const initializeDownload = createAction<{ id: string, size?: number, jobId?: number, location: string, image?: string }>('download/initialize');
|
||||
export const progressDownload = createAction<{ id: string, progress: number, jobId?: number }>('download/progress');
|
||||
export const completeDownload = createAction<{ id: string, location: string, size?: number, image?: string }>('download/complete');
|
||||
export const failDownload = createAction<{ id: string }>('download/fail');
|
||||
@@ -25,12 +25,13 @@ export const downloadTrack = createAsyncThunk(
|
||||
// Get the content-type from the URL by doing a HEAD-only request
|
||||
const [audioExt, imageExt] = await Promise.all([
|
||||
getExtensionForUrl(audioUrl),
|
||||
getExtensionForUrl(imageUrl)
|
||||
// Image files may be absent
|
||||
getExtensionForUrl(imageUrl).catch(() => null)
|
||||
]);
|
||||
|
||||
// Then generate the proper location
|
||||
const audioLocation = `${DocumentDirectoryPath}/${id}.${audioExt}`;
|
||||
const imageLocation = `${DocumentDirectoryPath}/${id}.${imageExt}`;
|
||||
const imageLocation = imageExt ? `${DocumentDirectoryPath}/${id}.${imageExt}` : undefined;
|
||||
|
||||
// Actually kick off the download
|
||||
const { promise: audioPromise } = downloadFile({
|
||||
@@ -48,24 +49,26 @@ export const downloadTrack = createAsyncThunk(
|
||||
toFile: audioLocation,
|
||||
});
|
||||
|
||||
const { promise: imagePromise } = downloadFile({
|
||||
fromUrl: imageUrl,
|
||||
toFile: imageLocation,
|
||||
background: true,
|
||||
});
|
||||
const { promise: imagePromise } = imageExt && imageLocation
|
||||
? downloadFile({
|
||||
fromUrl: imageUrl,
|
||||
toFile: imageLocation,
|
||||
background: true,
|
||||
})
|
||||
: { promise: Promise.resolve(null) };
|
||||
|
||||
// Await job completion
|
||||
const [audioResult, imageResult] = await Promise.all([audioPromise, imagePromise]);
|
||||
const totalSize = audioResult.bytesWritten + imageResult.bytesWritten;
|
||||
const totalSize = audioResult.bytesWritten + (imageResult?.bytesWritten || 0);
|
||||
dispatch(completeDownload({ id, location: audioLocation, size: totalSize, image: imageLocation }));
|
||||
},
|
||||
);
|
||||
|
||||
export const removeDownloadedTrack = createAsyncThunk(
|
||||
'/downloads/remove/track',
|
||||
async(id: string, { getState }) => {
|
||||
async (id: string, { getState }) => {
|
||||
// Retrieve the state
|
||||
const { downloads: { entities }} = getState() as AppState;
|
||||
const { downloads: { entities } } = getState() as AppState;
|
||||
|
||||
// Attempt to retrieve the entity from the state
|
||||
const download = entities[id];
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import db from 'mime-db';
|
||||
import mime from 'mime';
|
||||
|
||||
const MIME_OVERRIDES: Record<string, string> = {
|
||||
'audio/mpeg': 'mp3',
|
||||
'audio/ogg': '.ogg'
|
||||
'audio/ogg': '.ogg',
|
||||
'audio/flac': '.flac',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,11 @@ export async function getExtensionForUrl(url: string) {
|
||||
const response = await fetch(url, { method: 'HEAD' });
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
|
||||
// GUARD: Check that the request actually returned something
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to retrieve extension for URL: ' + response.statusText);
|
||||
}
|
||||
|
||||
// GUARD: Check that we received a content type
|
||||
if (!contentType) {
|
||||
throw new Error('Jellyfin did not return a Content-Type for a streaming URL.');
|
||||
@@ -23,21 +29,20 @@ export async function getExtensionForUrl(url: string) {
|
||||
}
|
||||
|
||||
// Alternatively, retrieve it from mime-db
|
||||
const extensions = db[contentType]?.extensions;
|
||||
|
||||
const extension = mime.getExtension(contentType);
|
||||
|
||||
// GUARD: Check that we received an extension
|
||||
if (!extensions?.length) {
|
||||
if (!extension) {
|
||||
console.error({ contentType, extension, url });
|
||||
throw new Error(`Unsupported MIME-type ${contentType}`);
|
||||
}
|
||||
|
||||
return extensions[0];
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a mime type by its extension
|
||||
*/
|
||||
export function getMimeTypeForExtension(extension: string) {
|
||||
return Object.keys(db).find((type) => {
|
||||
return db[type].extensions?.includes(extension);
|
||||
});
|
||||
return mime.getType(extension);
|
||||
}
|
||||
Reference in New Issue
Block a user