2013-12-10 5 views
6

Um eine Flasche Anwendung zu testen, habe ich ein Posting Anfrage Kolben Test-Client mit Dateien als AnhangWie mehrere Dateien mit Flask Test Client POST?

def make_tst_client_service_call1(service_path, method, **kwargs): 
    _content_type = kwargs.get('content-type','multipart/form-data') 
    with app.test_client() as client: 
     return client.open(service_path, method=method, 
          content_type=_content_type, buffered=True,    
              follow_redirects=True,**kwargs) 

def _publish_a_model(model_name, pom_env): 
    service_url = u'/publish/' 
    scc.data['modelname'] = model_name 
    scc.data['username'] = "BDD Script" 
    scc.data['instance'] = "BDD Stub Simulation" 
    scc.data['timestamp'] = datetime.now().strftime('%d-%m-%YT%H:%M') 
    scc.data['file'] = (open(file_path, 'rb'),file_name) 
    scc.response = make_tst_client_service_call1(service_url, method, data=scc.data) 

Flask Server Code Endpunkt, der die oben POST-Anfrage Griffe ist so etwas wie dieses

@app.route("/publish/", methods=['GET', 'POST']) 
def publish(): 
    if request.method == 'POST': 
     LOG.debug("Publish POST Service is called...") 
     upload_files = request.files.getlist("file[]") 
     print "Files :\n",request.files 
     print "Upload Files:\n",upload_files 
     return render_response_template() 

ich diesen Ausgang

Files: 
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>)]) 

Upload Files: 
[] 

Wenn ich

ändern
scc.data['file'] = (open(file_path, 'rb'),file_name) 

in (denken, dass es mehrere Dateien umgehen würde)

scc.data['file'] = [(open(file_path, 'rb'),file_name),(open(file_path, 'rb'),file_name1)] 

ich noch ähnliche Ausgabe erhalten:

Files: 
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>), ('file', <FileStorage: u'Second_XML.xml' ('application/xml')>)]) 

Upload Files: 
[] 

Frage: Warum request.files.getlist ("file []") gibt eine leere Liste zurück? Wie kann ich mehrere Dateien mit dem flash test client posten, so dass er unter Verwendung von request.files.getlist ("file []") auf der flash server-Seite abgerufen werden kann?

Hinweis:

  • Ich möchte Kolben-Client habe ich möchte nicht gewellt oder andere Client-basierten Lösungen.
  • Ich möchte nicht schon diese Links einzelne Datei in mehrere Anfragen

Dank

Geworben schreiben:

Flask and Werkzeug: Testing a post request with custom headers

Python - What type is flask.request.files.stream supposed to be?

Antwort

5

Sie die Dateien als Parameter senden benannt file, so dass Sie nicht mit t suchen können er Name file[]. Wenn Sie alle Dateien file als Liste mit dem Namen erhalten möchten, sollten Sie diese verwenden:

upload_files = request.files.getlist("file") 

Auf der anderen Seite, wenn Sie wirklich wollen von file[] lesen, dann müssen Sie sie so an:

scc.data['file[]'] = # ... 

(die file[] Syntax von PHP und es nur auf der Client-Seite verwendet wird. Wenn Sie die Parameter wie die an den Server mit dem Namen senden, haben Sie immer sie $_FILES['file'] mit zugreifen.

)
+0

Danke. Ja. Nach einem Blick durch den Code, für "getlist", wurde mir klar, dass getList am letzten Abend für einen bestimmten Schlüssel aus dem multiDict zurückkommt. Ich habe einen falschen Schlüsselnamen benutzt, weil ich nicht so gut verstanden habe. Wie auch immer, du hast meine Frage beantwortet und wirst deine annehmen. Auch veröffentlichte Informationen, die ich in meiner anderen Antwort gesammelt habe. – user2390183

2

Lukas bereits angesprochen dies, nur diese Informationen bereitstellt, wie es jemand

Werkzeug Klienten helfen kann einige clevere Sachen tut, indem er Anforderungen Daten in MultiDict Speicherung

@native_itermethods(['keys', 'values', 'items', 'lists', 'listvalues']) 
class MultiDict(TypeConversionDict): 
    """A :class:`MultiDict` is a dictionary subclass customized to deal with 
    multiple values for the same key which is for example used by the parsing 
    functions in the wrappers. This is necessary because some HTML form 
    elements pass multiple values for the same key. 

    :class:`MultiDict` implements all standard dictionary methods. 
    Internally, it saves all values for a key as a list, but the standard dict 
    access methods will only return the first value for a key. If you want to 
    gain access to the other values, too, you have to use the `list` methods as 
    explained below. 

getList Anruf für einen bestimmten Schlüssel sieht im Wörterbuch "Anfragen". Wenn der Schlüssel nicht existiert, gibt er eine leere Liste zurück.

def getlist(self, key, type=None): 
    """Return the list of items for a given key. If that key is not in the 
    `MultiDict`, the return value will be an empty list. Just as `get` 
    `getlist` accepts a `type` parameter. All items will be converted 
    with the callable defined there. 

    :param key: The key to be looked up. 
    :param type: A callable that is used to cast the value in the 
       :class:`MultiDict`. If a :exc:`ValueError` is raised 
       by this callable the value will be removed from the list. 
    :return: a :class:`list` of all the values for the key. 
    """ 
    try: 
     rv = dict.__getitem__(self, key) 
    except KeyError: 
     return [] 
    if type is None: 
     return list(rv) 
    result = [] 
    for item in rv: 
     try: 
      result.append(type(item)) 
     except ValueError: 
      pass 
    return result