简体   繁体   中英

upload file to django server using curl

On Django python server, I have customized a URL where users can upload files. Now, problem is that I am successfully able to upload files when I hit the browser but when I try same thing using curl, I am not able to do so.

views.py

import json

from django.http import HttpResponse
from django.template import Context, RequestContext
from django.shortcuts import render_to_response, get_object_or_404

# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from sdm.models import Document
from sdm.forms import DocumentForm

def lists(request):
   # Handle file upload
   if request.method == 'POST':
     form = DocumentForm(request.POST, request.FILES)
     if form.is_valid():
        newdoc = Document(docfile = request.FILES['docfile'])
        newdoc.save()

        # Redirect to the document list after POST
        return HttpResponseRedirect(reverse('sdm:lists'))

else:
    form = DocumentForm() # A empty, unbound form

# Load documents for the list page
documents = Document.objects.all()

# Render list page with the documents and the form
return render_to_response(
    'sdm/lists.html',
    {'documents': documents, 'form': form},
    context_instance=RequestContext(request)
)

........ ........ ........ ........

lists.html

 <!DOCTYPE html>
 <html>
 <head>
    <meta charset="utf-8">
    <title>Minimal Django File Upload Example</title>   
 </head>
 <body>
 <!-- List of uploaded documents -->
 {% if documents %}
    <ul>
    {% for document in documents %}
        <li><a href="{{document.docfile.url }}">{{ document.docfile.name }}</a></li>
    {% endfor %}
    </ul>
 {% else %}
    <p>No documents.</p>
 {% endif %}

    <!-- Upload form. Note enctype attribute! -->
    <form action="{% url sdm:lists %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p>{{form.non_field_errors }}</p>
        <p>{{form.docfile.label_tag }} {{form.docfile.help_text }}</p>
        <p>
            {{ form.docfile.errors }}
            {{ form.docfile }}
        </p>
        <p><input type="submit" name="press" value="Upload" /></p>
    </form>
 </body>
</html> 

On Browser

在此处输入图片说明

On Terminal, I tried

 $ curl --request PUT --upload-file filename http://wings.spectrumserver/sdm/lists

 $ curl --form upload-file=filename  --form press=Upload 

 http:// wings. spectrumserver/sdm/lists

$ curl --upload-file filename http://wings.spectrumserver/sdm/lists
$ curl --upload-file filename press=upload http://wings.spectrumserver/sdm/lists

$ curl -H 'Expect:' -F data=@filename -F submit=Upload wings.spectrumserver/sdm/lists

// In all cases, No error but no file upload

I tried some other variations but nothing seems working out. Also some other commands I tried which gives "NO csrf token error". I also tried removing csrf token entries form html file and setting.py but nothing worked.

I am all new to curl and python both. Main purpose is to upload file using some python script. I thought if I can upload through curl then same things can be replicated in python script with curl library so if this is not working out then can anyone suggest some python code to upload files to this server.

Edit :

$ curl -i -F name=press -F f13 wings.spectrumserver/sdm/lists
Warning: Illegally formatted input field!
curl: option -F: is badly used here
curl: try 'curl --help' or 'curl --manual' for more information

Edit2- Header Response (f13 is new file thats not included)

$ curl -i http://wings.spectrumserver/sdm/lists

HTTP/1.1 200 OK
Date: Thu, 07 Nov 2013 23:19:18 GMT Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding Content-Length: 1263 Content-Type: text/html; charset=utf-8

Minimal Django File Upload Example

    <ul>

        <li><a href="/media/documents/2013/10/28/templates.zip">documents/2013/10
    /28/templates.zip</a></li>

        <li><a href="/media/documents/2013/11/07/list">documents/2013/11/07/list</a>
    </li>

        <li><a href="/media/documents/2013/11/07/f1">documents/2013/11/07/f1</a></li>

        <li><a href="/media/documents/2013/11/07/f12">documents/2013/11/07/f12</a></li>

        <li><a href="/media/documents/2013/11/07/hello.html">documents/2013/11
        /07/hello.html</a></li>

    </ul>


    <!-- Upload form. Note enctype attribute! -->
    <form action="/sdm/lists" method="post" enctype="multipart/form-data">

   <!--            
   -->        <p></p>
        <p><label for="id_docfile">Select a file</label> max. 42 megabytes</p>
        <p>

            <input type="file" name="docfile" id="id_docfile" />
        </p>
        <p><input type="submit" name="press" value="Upload" /></p>
    </form>
  </body>
</html> 

Try something like this:

curl -i --form docfile=@localfilename http://wings.spectrumserver/sdm/lists

If doesn't work, post your header response. -i tells curl to print the header response.

I think its the CSRF token that is missing.

{% csrf_token %}

look at django docs Cross Site Request Forgery protection . Its is a token generated to make sure the form is submitted from the same domain. you can either disable the CSRF protection by removing the tag from the template. or try here on how to pass it using curl.

btw if all you want is uploading using a python script i would recommend using requests .

url = 'http://wings.spectrumserver/sdm/lists'
files = {'file': open('file.ext', 'rb')}
r = requests.post(url, files=files)

I can't help to solv this with curl.

But if you can program python3:

Django have a protection for Cross Site Reference Forgery (CSRF)

You need to use the CSRF cookie and the hidden CSRF in the FORM.

So you need first GET the download page (like a browser), extract the CSRFs and make the POST including this data.

And the POST must be in multipart/form-data format.

One way to see how this format is, in a Linux machine:

1 - Create a Django upload page where the form ACTION point to (say) http://127.0.0.1:2222/

2 - Open a terminal and execute: nc -l 127.0.0.1 2222 &1 | less

3 - Open the browser in the upload page, fill the form with some small text to upload, and press the upload button. The browser will complain, no problem...

4 - In the terminal you will see how the browser uploads the file using POST & multipart/data-form

To implemente a solution:

5 - Check the link http://blog.spotflux.com/uploading-files-python-3 where it uses python3 to make the POST in multipart/form-data format.

6 - You will need to make some changes in this example to include the cookie in the post.

Use html.parser.HTMLParser to parse the HTML page.

It works fine, but I can't post the code.

I didn't try to use requests.get() and requests.post().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM