Swift使用Alamofire向MathPix API上传本地图片遇内部错误求助
解决MathPix API本地图片上传内部错误问题
环境:Swift 5 / Alamofire 5 / Xcode / iOS
我尝试将拍摄的照片上传至MathPix API,但一直返回Internal error。仅使用网络图片链接时请求正常,Mac终端用curl上传本地图片也没问题,确定是请求语法问题。
官方示例代码
cURL示例
curl -X POST https://api.mathpix.com/v3/text \ -H 'app_id: APP_ID' \ -H 'app_key: APP_KEY' \ --form 'file=@"cases_hw.jpg"' \ --form 'options_json="{\"math_inline_delimiters\": [\"$\", \"$\"], \"rm_spaces\": true}"'
Python示例
#!/usr/bin/env python import requests import json r = requests.post("https://api.mathpix.com/v3/text", files={"file": open("cases_hw.jpg","rb")}, data={ "options_json": json.dumps({ "math_inline_delimiters": ["$", "$"], "rm_spaces": True }) }, headers={ "app_id": "APP_ID", "app_key": "APP_KEY" } ) print(json.dumps(r.json(), indent=4, sort_keys=True))
我的Swift代码
变量定义
@State private var selectedImage: UIImage? // 拍摄的照片存储在此处 @State private var imagePath = "" // 图片完整路径
请求函数
let image = selectedImage let imageData = image!.jpegData(compressionQuality: 1.0)! let imageKey = "takenPhoto" let urlString = "https://api.mathpix.com/v3/text" let headers: HTTPHeaders = [ "app_id": "my_working_app_id_here", "app_key": "my_working_app_key_here" ] AF.upload(multipartFormData: { multiPart in multiPart.append(imageData, withName: imageKey, fileName: "takenPhoto.jpg", mimeType: "image/jpg") }, to: urlString, headers: headers).responseJSON { response in switch response.result { case .success(_): if let dictionary = response.value as? [String:Any] { print("success", dictionary) } else { print("error") } case .failure(let error): print("error", error.localizedDescription) } }
返回错误信息
["error": Internal error, "error_info": { id = "sys_exception"; message = "Internal error"; }]
其他尝试
使用CurlDSL构造请求,仍返回相同错误:
try CURL("curl -X POST https://api.mathpix.com/v3/text -H \'app_id: my_app_id_here\' -H \'app_key: my_app_key_here\' -F image@=\(homeDirectoryString)")
解决方案
问题出在两个核心点:
- 表单字段名不匹配:MathPix API要求图片字段名为
file,你用的是takenPhoto,导致API无法识别图片参数。 - 缺少必填的
options_json参数:官方示例中均包含该参数,你的请求未添加,这是触发内部错误的关键原因。
修正后的请求代码:
let image = selectedImage guard let imageData = image?.jpegData(compressionQuality: 1.0) else { return } let urlString = "https://api.mathpix.com/v3/text" let headers: HTTPHeaders = [ "app_id": "my_working_app_id_here", "app_key": "my_working_app_key_here" ] // 构造options参数 let options = [ "math_inline_delimiters": ["$", "$"], "rm_spaces": true ] guard let optionsData = try? JSONSerialization.data(withJSONObject: options) else { return } let optionsString = String(data: optionsData, encoding: .utf8)! AF.upload(multipartFormData: { multiPart in // 图片字段名改为`file`,和官方示例一致 multiPart.append(imageData, withName: "file", fileName: "takenPhoto.jpg", mimeType: "image/jpeg") // 添加options_json参数 multiPart.append(optionsString.data(using: .utf8)!, withName: "options_json") }, to: urlString, headers: headers).responseJSON { response in switch response.result { case .success(let value): if let dictionary = value as? [String:Any] { print("success", dictionary) } case .failure(let error): print("error", error.localizedDescription) } }
额外注意事项
- 用
guard判断jpegData是否为空,避免强制解包导致崩溃。 - MIME类型使用标准的
image/jpeg而非image/jpg。 - 若仍有问题,可开启Alamofire日志功能,对比实际发送的请求与终端curl的请求头、表单数据差异。
内容的提问来源于stack exchange,提问作者Skill Kolen
相关产品推荐
相关产品推荐

