fix: improve file path handling in API routes
- Updated file reading and database querying logic to decode URL-encoded paths, ensuring proper handling of special characters. - Refactored path usage in the GET requests for both media file listing and content retrieval, enhancing compatibility with various file names.
This commit is contained in:
parent
89930b833c
commit
fbeed219fc
BIN
data/media.db
BIN
data/media.db
Binary file not shown.
|
|
@ -13,20 +13,23 @@ export async function GET(request: Request) {
|
||||||
return NextResponse.json({ error: "Path is required" }, { status: 400 });
|
return NextResponse.json({ error: "Path is required" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode the URL-encoded path to handle special characters
|
||||||
|
const decodedFilePath = decodeURIComponent(filePath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Validate file exists
|
// Validate file exists
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!fs.existsSync(decodedFilePath)) {
|
||||||
return NextResponse.json({ error: "File not found" }, { status: 404 });
|
return NextResponse.json({ error: "File not found" }, { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a file (not directory)
|
// Check if it's a file (not directory)
|
||||||
const stats = fs.statSync(filePath);
|
const stats = fs.statSync(decodedFilePath);
|
||||||
if (!stats.isFile()) {
|
if (!stats.isFile()) {
|
||||||
return NextResponse.json({ error: "Path is not a file" }, { status: 400 });
|
return NextResponse.json({ error: "Path is not a file" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a text file
|
// Check if it's a text file
|
||||||
const ext = path.extname(filePath).toLowerCase().replace('.', '');
|
const ext = path.extname(decodedFilePath).toLowerCase().replace('.', '');
|
||||||
if (!TEXT_EXTENSIONS.includes(ext)) {
|
if (!TEXT_EXTENSIONS.includes(ext)) {
|
||||||
return NextResponse.json({ error: "File type not supported" }, { status: 400 });
|
return NextResponse.json({ error: "File type not supported" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
@ -41,10 +44,10 @@ export async function GET(request: Request) {
|
||||||
let content = '';
|
let content = '';
|
||||||
try {
|
try {
|
||||||
if (encoding === 'utf8') {
|
if (encoding === 'utf8') {
|
||||||
content = fs.readFileSync(filePath, 'utf-8');
|
content = fs.readFileSync(decodedFilePath, 'utf-8');
|
||||||
} else {
|
} else {
|
||||||
// For non-UTF-8 encodings, read as buffer and convert
|
// For non-UTF-8 encodings, read as buffer and convert
|
||||||
const buffer = fs.readFileSync(filePath);
|
const buffer = fs.readFileSync(decodedFilePath);
|
||||||
const iconv = require('iconv-lite');
|
const iconv = require('iconv-lite');
|
||||||
content = iconv.decode(buffer, encoding);
|
content = iconv.decode(buffer, encoding);
|
||||||
}
|
}
|
||||||
|
|
@ -55,9 +58,9 @@ export async function GET(request: Request) {
|
||||||
for (const fallbackEncoding of fallbackEncodings) {
|
for (const fallbackEncoding of fallbackEncodings) {
|
||||||
try {
|
try {
|
||||||
if (fallbackEncoding === 'utf8') {
|
if (fallbackEncoding === 'utf8') {
|
||||||
content = fs.readFileSync(filePath, 'utf-8');
|
content = fs.readFileSync(decodedFilePath, 'utf-8');
|
||||||
} else {
|
} else {
|
||||||
const buffer = fs.readFileSync(filePath);
|
const buffer = fs.readFileSync(decodedFilePath);
|
||||||
const iconv = require('iconv-lite');
|
const iconv = require('iconv-lite');
|
||||||
content = iconv.decode(buffer, fallbackEncoding);
|
content = iconv.decode(buffer, fallbackEncoding);
|
||||||
}
|
}
|
||||||
|
|
@ -74,13 +77,13 @@ export async function GET(request: Request) {
|
||||||
// If no encoding worked, try reading as buffer and return as base64
|
// If no encoding worked, try reading as buffer and return as base64
|
||||||
if (!content || content.length === 0) {
|
if (!content || content.length === 0) {
|
||||||
try {
|
try {
|
||||||
const buffer = fs.readFileSync(filePath);
|
const buffer = fs.readFileSync(decodedFilePath);
|
||||||
content = buffer.toString('base64');
|
content = buffer.toString('base64');
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
content,
|
content,
|
||||||
size: stats.size,
|
size: stats.size,
|
||||||
path: filePath,
|
path: decodedFilePath,
|
||||||
name: path.basename(filePath),
|
name: path.basename(decodedFilePath),
|
||||||
encoding: 'base64'
|
encoding: 'base64'
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -91,8 +94,8 @@ export async function GET(request: Request) {
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
content,
|
content,
|
||||||
size: stats.size,
|
size: stats.size,
|
||||||
path: filePath,
|
path: decodedFilePath,
|
||||||
name: path.basename(filePath),
|
name: path.basename(decodedFilePath),
|
||||||
encoding: encoding
|
encoding: encoding
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,22 @@ export async function GET(request: Request) {
|
||||||
return NextResponse.json({ error: "Path is required" }, { status: 400 });
|
return NextResponse.json({ error: "Path is required" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode the URL-encoded path to handle special characters like +, spaces, Chinese characters, etc.
|
||||||
|
const decodedPath = decodeURIComponent(dirPath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const db = getDatabase();
|
const db = getDatabase();
|
||||||
const files = fs.readdirSync(dirPath);
|
const files = fs.readdirSync(decodedPath);
|
||||||
|
|
||||||
// Get media files from database for this path
|
// Get media files from database for this path
|
||||||
const mediaFiles = db.prepare(`
|
const mediaFiles = db.prepare(`
|
||||||
SELECT id, path, type, thumbnail, avg_rating, star_count
|
SELECT id, path, type, thumbnail, avg_rating, star_count
|
||||||
FROM media
|
FROM media
|
||||||
WHERE path LIKE ?
|
WHERE path LIKE ?
|
||||||
`).all(`${dirPath}%`) as Array<{id: number, path: string, type: string, thumbnail: string | null, avg_rating: number, star_count: number}>;
|
`).all(`${decodedPath}%`) as Array<{id: number, path: string, type: string, thumbnail: string | null, avg_rating: number, star_count: number}>;
|
||||||
|
|
||||||
const result = files.map((file) => {
|
const result = files.map((file) => {
|
||||||
const filePath = path.join(dirPath, file);
|
const filePath = path.join(decodedPath, file);
|
||||||
const stats = fs.statSync(filePath);
|
const stats = fs.statSync(filePath);
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue