在Django python服务器上,我已经定制了一个用户可以上传文件的URL。现在,问题是当我点击浏览器时我成功上传文件但是当我使用curl尝试相同的事情时,我无法这样做。
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>
在浏览器上
在终端上,我尝试了
$ 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
我尝试了其他一些变化,但似乎没有任何结果。我试过的其他一些命令也给出了“NO csrf token error”。我还尝试从csrf token
和html file
删除setting.py
个条目,但没有任何效果。
我对curl和python都很陌生。主要目的是使用一些python脚本上传文件。我想如果我可以通过curl上传然后可以在python脚本中使用curl库复制相同的东西,所以如果这没有用,那么任何人都可以建议一些python代码将文件上传到这个服务器。
修改:
$ 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-标头响应(f13是未包含的新文件)
$ curl -i http://wings.spectrumserver/sdm/lists
HTTP / 1.1 200 OK
日期:星期四,2013年11月7日23:19:18 GMT
服务器:Apache / 2.2.22(Ubuntu)
变化:接受编码
内容长度:1263
内容类型:text / html;字符集= UTF-8
最小的Django文件上传示例
<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>
答案 0 :(得分:3)
尝试这样的事情:
curl -i --form docfile=@localfilename http://wings.spectrumserver/sdm/lists
如果不起作用,请发布标题回复。 -i
告诉curl打印标题响应。
答案 1 :(得分:0)
我认为它缺少了CSRF令牌。
{% csrf_token %}
看看django docs Cross Site Request Forgery protection。 它是一个生成的标记,用于确保表单是从同一个域提交的。 您可以通过从模板中删除标记来禁用CSRF保护。 或尝试here如何使用curl传递它。
顺便说一句,如果您只想使用python脚本上传,我建议使用requests。
url = 'http://wings.spectrumserver/sdm/lists'
files = {'file': open('file.ext', 'rb')}
r = requests.post(url, files=files)
答案 2 :(得分:0)
我无法用卷曲来解决这个问题。
但是如果你可以编程python3:
Django对Cross Site Reference Forgery(CSRF)提供保护
您需要在FORM中使用CSRF cookie和隐藏的CSRF。
因此,首先需要获取下载页面(如浏览器),解压缩CSRF并使POST包含此数据。
POST必须是多部分/表格数据格式。
在Linux机器中查看此格式的一种方法:
1 - 创建一个Django上传页面,其中表格ACTION指向(例如)http://127.0.0.1:2222/
2 - 打开终端并执行: nc -l 127.0.0.1 2222&amp; 1 |少
3 - 在上传页面中打开浏览器,填写表格并上传一些小文本,然后按上传按钮。浏览器会抱怨,没问题......
4 - 在终端中,您将看到浏览器如何使用POST&amp;和浏览器上传文件。多部分/数据形式
实施解决方案:
5 - 检查链接http://blog.spotflux.com/uploading-files-python-3,它使用python3以多部分/表格数据格式进行POST。
6 - 您需要在此示例中进行一些更改,以便在帖子中包含Cookie。
使用html.parser.HTMLParser解析HTML页面。
它工作正常,但我无法发布代码。
我没有尝试使用requests.get()和requests.post()。