fix: 解决下载文件后缀的问题

This commit is contained in:
oliviamn 2025-07-17 01:07:13 +08:00
parent 68765ab45f
commit edad8e7322
4 changed files with 119 additions and 3 deletions

View File

@ -61,6 +61,58 @@ docker-compose logs -f mineru-api
docker-compose logs -f frontend
```
## Building Services
### Building all services
```bash
# Build all services
docker-compose build
# Build and start all services
docker-compose up -d --build
```
### Building individual services
```bash
# Build only backend
docker-compose build backend-api
# Build only frontend
docker-compose build frontend
# Build only mineru
docker-compose build mineru-api
# Build multiple specific services
docker-compose build backend-api frontend
```
### Building and restarting specific services
```bash
# Build and restart only backend
docker-compose build backend-api
docker-compose up -d backend-api
# Or combine in one command
docker-compose up -d --build backend-api
# Build and restart backend and celery worker
docker-compose up -d --build backend-api celery-worker
```
### Force rebuild (no cache)
```bash
# Force rebuild all services
docker-compose build --no-cache
# Force rebuild specific service
docker-compose build --no-cache backend-api
```
## Environment Variables
The unified setup uses environment variables from the individual service `.env` files:
@ -122,7 +174,7 @@ If you get port conflicts, you can modify the port mappings in the `docker-compo
```yaml
ports:
- "8001:8000" # Change 8001 to any available port
- "8002:8000" # Change external port
```
### Volume Issues

View File

@ -94,6 +94,25 @@ docker-compose logs -f [service-name]
docker-compose ps
```
### Building Individual Services
```bash
# Build specific service only
docker-compose build backend-api
docker-compose build frontend
docker-compose build mineru-api
# Build and restart specific service
docker-compose up -d --build backend-api
# Force rebuild (no cache)
docker-compose build --no-cache backend-api
# Using the build script
./build-service.sh backend-api --restart
./build-service.sh frontend --no-cache
./build-service.sh backend-api celery-worker
```
## 🌐 Service URLs
After successful migration:

View File

@ -79,26 +79,49 @@ async def download_file(
file_id: str,
db: Session = Depends(get_db)
):
print(f"=== DOWNLOAD REQUEST ===")
print(f"File ID: {file_id}")
file = db.query(FileModel).filter(FileModel.id == file_id).first()
if not file:
print(f"❌ File not found for ID: {file_id}")
raise HTTPException(status_code=404, detail="File not found")
print(f"✅ File found: {file.filename}")
print(f"File status: {file.status}")
print(f"Original path: {file.original_path}")
print(f"Processed path: {file.processed_path}")
if file.status != FileStatus.SUCCESS:
print(f"❌ File not ready for download. Status: {file.status}")
raise HTTPException(status_code=400, detail="File is not ready for download")
if not os.path.exists(file.processed_path):
print(f"❌ Processed file not found at: {file.processed_path}")
raise HTTPException(status_code=404, detail="Processed file not found")
print(f"✅ Processed file exists at: {file.processed_path}")
# Get the original filename without extension and add .md extension
original_filename = file.filename
filename_without_ext = os.path.splitext(original_filename)[0]
download_filename = f"{filename_without_ext}.md"
return FileResponse(
print(f"Original filename: {original_filename}")
print(f"Filename without extension: {filename_without_ext}")
print(f"Download filename: {download_filename}")
response = FileResponse(
path=file.processed_path,
filename=download_filename,
media_type="text/markdown"
)
print(f"Response headers: {dict(response.headers)}")
print(f"=== END DOWNLOAD REQUEST ===")
return response
@router.websocket("/ws/status/{file_id}")
async def websocket_endpoint(websocket: WebSocket, file_id: str, db: Session = Depends(get_db)):

View File

@ -47,15 +47,37 @@ const FileList: React.FC<FileListProps> = ({ files, onFileStatusChange }) => {
const handleDownload = async (fileId: string) => {
try {
console.log('=== FRONTEND DOWNLOAD START ===');
console.log('File ID:', fileId);
const file = files.find((f) => f.id === fileId);
console.log('File object:', file);
const blob = await api.downloadFile(fileId);
console.log('Blob received:', blob);
console.log('Blob type:', blob.type);
console.log('Blob size:', blob.size);
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = files.find((f) => f.id === fileId)?.filename || 'downloaded-file';
// Match backend behavior: change extension to .md
const originalFilename = file?.filename || 'downloaded-file';
const filenameWithoutExt = originalFilename.replace(/\.[^/.]+$/, ''); // Remove extension
const downloadFilename = `${filenameWithoutExt}.md`;
console.log('Original filename:', originalFilename);
console.log('Filename without extension:', filenameWithoutExt);
console.log('Download filename:', downloadFilename);
a.download = downloadFilename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
console.log('=== FRONTEND DOWNLOAD END ===');
} catch (error) {
console.error('Error downloading file:', error);
}