从 iOS 上传 Flask 文件
Posted
技术标签:
【中文标题】从 iOS 上传 Flask 文件【英文标题】:Flask file uploads from iOS 【发布时间】:2015-08-27 21:34:33 【问题描述】:我正在尝试将音频文件从我的 ios 应用程序上传到我的烧瓶后端。 POST 请求通过,但我收到一条错误消息,提示“浏览器(或代理)发送了此服务器无法理解的请求。”
我正在查看烧瓶文档来执行此操作,但我看不出他们在做什么不同。
@auth.route('/uploadfile', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
print('post request received')
file = request.files['file']
if file and allowed_file(file.filename):
print('file name is valid and saving')
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify('success': 1)
else:
print('file failed to save')
return jsonify('success': 2)
def allowed_file(filename):
print('in allowed_file')
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['AllOWED_EXTENSIONS']
//Config settings
UPLOAD_FOLDER = '/Users/Michael/Desktop/uploads'
ALLOWED_EXTENSIONS = set(['m4a'])
iOS 端
func savePressed()
var stringVersion = recordingURL?.path
let encodedSound = NSFileManager.defaultManager().contentsAtPath(stringVersion!)
let encodedBase64Sound = encodedSound!.base64EncodedStringWithOptions(nil)
let dict = ["file": encodedBase64Sound]
let urlString = "http://127.0.0.1:5000/auth/uploadfile"
var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "Post"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(dict as NSDictionary, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//Completion handler
var task = session.dataTaskWithRequest(request, completionHandler: data, response, error -> Void in
【问题讨论】:
【参考方案1】:您正在对文件进行 base64 编码,并将其发布到具有 application/json
类型的 JSON 对象中。 files
仅在发出 multipart/form-data
类型的请求时才会填充。
因此,request.files
中没有名为“file”的数据,而是request.json
中的 base64 编码字符串“file”。当您尝试访问请求集合中不存在的键时,Flask 会引发错误。
您当前的方式有效,您仍然可以将字符串解码回二进制并保存,但您需要生成自己的文件名或单独发送。
from base64 import b64decode
b64_data = request.json['file'] # the base64 encoded string
bin_data = base64decode(b64_data) # decode it into bytes
# perhaps send the filename as part of the JSON as well, or make one up locally
filename = secure_filename(request.json['filename'])
with open(filename, 'wb') as f:
f.write(bin_data) # write the decoded bytes
正确的解决方法是将帖子设为multipart/form-data
,并将文件放在正文的文件部分。我不知道如何在 iOS 中执行此操作,但绝对应该支持它。这是使用 Python requests 库的帖子的样子。如果你能在 iOS 中得到等价物,那么你就不必更改 Flask 代码。
with open(recording, 'rb') as f:
requests.post('http://127.0.0.1:5000/auth/uploadfile', files='file': f)
【讨论】:
以上是关于从 iOS 上传 Flask 文件的主要内容,如果未能解决你的问题,请参考以下文章