24

I am trying to upload a file to a server using curl and python flask. Below I have the code of how I have implemented it. Any ideas on what I am doing wrong.

curl -i -X PUT -F name=Test -F filedata=@SomeFile.pdf "http://localhost:5000/" 

@app.route("/", methods=['POST','PUT'])
def hello():
    file = request.files['Test']
    if file and allowed_file(file.filename):
        filename=secure_filename(file.filename)
        print filename

    return "Success"

The following is the error that the server sends back

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not understand.</p>

Thanks in advance.

anonymous123
  • 1,271
  • 6
  • 19
  • 43
  • 1
    Your code works if you POST the data, e.g. `curl -F "Test=@SomeFile.pdf" http://127.0.0.1:5000` which therefore narrows your problem down to how you're handling PUT requests in Flask. – Doobeh Jun 26 '13 at 20:31
  • I remember some thread which says that request.files does not work with PUT. Can you try request.data instead ? – codegeek Jun 26 '13 at 20:40
  • Your code looks good, what do you get if you try:curl -X PUT -F Test=@foo.txt http://localhost:5000 – snahor Jun 26 '13 at 20:44
  • @codegeek - it works just fine with either PUT or POST. – mata Jun 26 '13 at 21:25
  • @snahor how this command should look on Windows? '@foo.txt' is not working... curl.exe -X PUT -F Test=...?... localhost:5000 – Piotr Jul 01 '15 at 23:12
  • @Piotr AFAIK it should work on windows. What is the output of running that? – snahor Jul 02 '15 at 03:44
  • yeah... so how is it working exactly? is @foo.txt replaced with the content of the file? I am getting it on a server side, but I am wondering how is it working exactly – Piotr Jul 02 '15 at 20:21

2 Answers2

19

Your curl command means you're transmitting two form contents, one file called filedata, and one form field called name. So you can do this:

file = request.files['filedata']   # gives you a FileStorage
test = request.form['name']        # gives you the string 'Test'

but request.files['Test'] doesn't exist.

mata
  • 67,110
  • 10
  • 163
  • 162
  • how do you add the files ? – Dinesh Mar 27 '17 at 17:47
  • @DineshVG I'm not sure what you mean with your question. The curl command sends a post request with the given file or form data to the server where they can be accessed in the route on the request object as shown. – mata Mar 27 '17 at 22:15
  • I have a html page through which I - send a post request - by attaching a file I tried it using a curl command, it didn't work. I figured out later... I had to give two key-value pairs.. One for the name of the file and another for the file itself. And got it to work.. – Dinesh Mar 29 '17 at 10:32
9

I have had quite a bit of issues getting this to work, so here is a very explicit solution:

Here we make a simple flask app that has two routes, one to test if the app works ("Hello World") and one to print the file name (To ensure we get a hold of the file).

from flask import Flask, request
from werkzeug.utils import secure_filename

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "Hello World"

@app.route("/print_filename", methods=['POST','PUT'])
def print_filename():
    file = request.files['file']
    filename=secure_filename(file.filename)   
    return filename

if __name__=="__main__":
    app.run(port=6969, debug=True)

First we test if we can even contact the app:

curl http://localhost:6969
>Hello World

Now let us POST a file and get its filename. We refer to the file with "file=" as the "request.files['file']" refers to "file". Here we go to a directory with a file in it called "test.txt":

curl -X POST -F file=@test.txt http://localhost:6969/print_filename
>test.txt

Finally we want to use paths to files:

curl -X POST -F file=@"/path/to/my/file/test.txt" http://localhost:6969/print_filename
>test.txt

Now that we have confirmed that we can actually get a hold of the file, then you can do whatever with it that you want with standard Python code.

Esben Eickhardt
  • 3,183
  • 2
  • 35
  • 56