问题
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>
回答1:
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.
回答2:
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)
回答3:
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().
来源:https://stackoverflow.com/questions/19848385/upload-file-to-django-server-using-curl