如何在FastAPI中不依赖python-multipart实现Angular文件上传
在FastAPI中无需python-multipart接收Angular上传的文件
如果不想依赖python-multipart,可以通过Base64编码嵌入JSON或直接传输二进制数据两种方式实现文件上传,以下是具体实现方案:
方案一:Base64编码嵌入JSON请求体
后端FastAPI实现
定义数据模型
用Pydantic创建模型,接收前端传来的文件名和Base64编码的文件内容:from pydantic import BaseModel, validator import base64 import os from fastapi import FastAPI, HTTPException app = FastAPI() class FileUploadRequest(BaseModel): filename: str file_content: str @validator('file_content') def strip_base64_prefix(cls, value): # 移除Base64字符串的前缀(如data:image/png;base64,) if 'base64,' in value: return value.split('base64,')[1] return value实现文件上传接口
解码Base64内容并保存到指定文件夹:TARGET_FOLDER = "./uploaded_files" # 确保目标文件夹存在 os.makedirs(TARGET_FOLDER, exist_ok=True) @app.post("/upload-file") async def upload_file(request: FileUploadRequest): try: # 解码Base64内容 file_bytes = base64.b64decode(request.file_content) # 拼接保存路径 save_path = os.path.join(TARGET_FOLDER, request.filename) # 写入文件 with open(save_path, "wb") as f: f.write(file_bytes) return {"message": f"文件 {request.filename} 上传成功", "save_path": save_path} except Exception as e: raise HTTPException(status_code=500, detail=f"上传失败: {str(e)}")
前端Angular实现
- 文件选择与Base64转换
在组件中监听文件选择事件,将文件转为Base64字符串并发起请求:import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-file-upload', template: ` <input type="file" (change)="onFilePick($event)"> <button (click)="submitUpload()" [disabled]="!selectedFile">上传</button> ` }) export class FileUploadComponent { selectedFile: File | null = null; fileBase64: string = ''; constructor(private http: HttpClient) {} onFilePick(event: Event): void { const input = event.target as HTMLInputElement; if (input.files?.length) { this.selectedFile = input.files[0]; const reader = new FileReader(); reader.onload = (e) => { this.fileBase64 = e.target?.result as string; }; reader.readAsDataURL(this.selectedFile); } } submitUpload(): void { if (!this.selectedFile || !this.fileBase64) return; const payload = { filename: this.selectedFile.name, file_content: this.fileBase64 }; this.http.post('http://localhost:8000/upload-file', payload) .subscribe({ next: res => console.log('上传成功:', res), error: err => console.error('上传失败:', err) }); } }
方案二:直接传输二进制数据
如果不想用Base64(避免体积膨胀),可直接发送二进制数据,后端读取原始请求体:
后端调整
from fastapi import Request @app.post("/upload-binary") async def upload_binary(request: Request): try: # 从请求头获取文件名 filename = request.headers.get("X-Filename") if not filename: raise HTTPException(status_code=400, detail="缺少请求头X-Filename") # 读取原始二进制数据 file_bytes = await request.body() save_path = os.path.join(TARGET_FOLDER, filename) with open(save_path, "wb") as f: f.write(file_bytes) return {"message": f"文件 {filename} 上传成功", "save_path": save_path} except Exception as e: raise HTTPException(status_code=500, detail=f"上传失败: {str(e)}")
前端调整
submitBinaryUpload(): void { if (!this.selectedFile) return; const headers = new Headers(); headers.append('X-Filename', this.selectedFile.name); this.http.post('http://localhost:8000/upload-binary', this.selectedFile, { headers }) .subscribe({ next: res => console.log('二进制上传成功:', res), error: err => console.error('二进制上传失败:', err) }); }
内容的提问来源于stack exchange,提问作者Ramyaa R
相关产品推荐
相关产品推荐

