烧瓶文件上传无法获取表单数据

时间:2018-08-09 11:14:43

标签: python angular flask

角度4 烧瓶1.0.2

大家好

我试图通过填充一个新的FormData()对象并将其发布来从Angular上传文件。它似乎可以正常发布,但是我无法从Flask中获取该帖子中的值。

我通过按钮点击事件来调用它:

UploadFile() : void{
    let formModel = new FormData()
    formModel.set('fileName', this.fileName);
    formModel.set('fileData', this.form.get('fileData').value);

    this.filesProvider.UploadFile(formModel)
      .subscribe(res => {
      this.UploadFileProcessed(res, true);
    }
    , (err) => {
      this.UploadFileProcessed(err, false);
    }
);

...呼叫提供者...

UploadFile(formData: FormData) : Observable<Response> {

    let headers = new Headers();
    headers.set('Content-Type', null);
    headers.set('Accept', "multipart/form-data");
    headers.set('Authorization', 'Basic ' + btoa(access_token + ":"));
    let requestOptions = new RequestOptions({ headers: headers })

    return this.http
    .post(this.globalVarsProvider.apiUrl + "member/uploadFile", formData, requestOptions)
    .map((response: Response) => response);
}

在Flask API端,我有这个:

@app.route('/api/member/uploadFile', methods=['POST'])
@auth.login_required
def uploadFile(): 
    print request.form.get('key1')
    return "ok"

在Flask dev服务器终端中运行此命令将输出“ None”。

如果我做print request.get_data(),我会看到所有的帖子数据(包括疯狂的图片数据)。

在Chrome中,请求如下所示:

enter image description here

请问我在做什么错,以及如何从Flask中获取数据?

谢谢!

1 个答案:

答案 0 :(得分:2)

您做错了两件事:

  • 您将Content-Type标头设置为null,因此将其保留为空。现在Angular无法告诉服务器如何拆分multipart/form请求的不同部分。

  • 您没有在服务器端访问正确的字段。

您完全不应该设置Content-Type标头,因此请删除headers.set('Content-Type', null)调用。角度4然后从sets the header for youmultipart/form-data,并将在该标头中包含边界值(请求主体中字段之间的字符串)。

您的Flask代码正在尝试访问不存在的字段。您的前端代码发布了两个字段:

formModel.set('fileName', this.fileName);
formModel.set('fileData', this.form.get('fileData').value);

和您的屏幕快照确认确实发布了fileNamefileData部分。但是您的Flask代码尝试访问key1

print request.form.get('key1')

没有此类键,因此.get()方法将返回默认值None

对于文件上传,您确实要使用request.files attribute;请参阅该属性和requests.form attribute的文档:

  

form :具有MultiDictPOST请求中解析出的表单数据的PUT。请记住,文件上传不会在这里结束,而是在files属性中。

     

[...]

     

files :一个MultiDict,其中包含作为POSTPUT请求的一部分上传的文件。每个文件都存储为FileStorage对象。它的行为基本上就像您从Python知道的标准文件对象一样,不同之处在于它还有一个save()函数可以将文件存储在文件系统中。

因此,使用request.form['fileName']request.files['fileData']访问这两个字段。

另请参阅Uploading Files pattern documentation

作为旁注:您不应设置Accept标头。 Accept标头用于客户端(例如您的浏览器)告诉服务器可接受哪种响应Accept: multipart/form告诉服务器您希望它以multipart/form响应来响应。它没有说明请求本身的内容。如果您的示例来自对this blog post (a top Google hit for "angular 4 form-data upload")的注释,则该注释者会以无效代码误导您。我在此处添加了评论,至少可以帮助将来的访问者避免该错误。