파이썬 요청 파일 업로드


124

Python 요청 라이브러리를 사용하여 파일을 업로드하는 간단한 작업을 수행하고 있습니다. Stack Overflow를 검색했는데 아무도 같은 문제가없는 것 같았습니다. 즉, 파일이 서버에서 수신되지 않는다는 것입니다.

import requests
url='http://nesssi.cacr.caltech.edu/cgi-bin/getmulticonedb_release2.cgi/post'
files={'files': open('file.txt','rb')}
values={'upload_file' : 'file.txt' , 'DB':'photcat' , 'OUT':'csv' , 'SHORT':'short'}
r=requests.post(url,files=files,data=values)

'upload_file'키워드의 값을 내 파일 이름으로 채 웁니다. 비워두면

Error - You must select a file to upload!

그리고 이제 나는

File  file.txt  of size    bytes is  uploaded successfully!
Query service results:  There were 0 lines.

파일이 비어있는 경우에만 나타납니다. 그래서 내 파일을 성공적으로 보내는 방법에 대해 고민했습니다. 이 웹 사이트로 이동하여 양식을 수동으로 채우면 일치하는 개체의 멋진 목록이 반환되므로 파일이 작동한다는 것을 알고 있습니다. 모든 힌트에 감사드립니다.

관련된 다른 스레드 (그러나 내 문제에 대답하지 않음) :

답변:


211

경우 upload_file파일 사용으로 의미 :

files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}

r = requests.post(url, files=files, data=values)

requests으로 여러 부분으로 형성 POST 본체 보낼 upload_file의 내용에 필드 세트file.txt 파일.

파일 이름은 특정 필드의 MIME 헤더에 포함됩니다.

>>> import requests
>>> open('file.txt', 'wb')  # create an empty demo file
<_io.BufferedWriter name='file.txt'>
>>> files = {'upload_file': open('file.txt', 'rb')}
>>> print(requests.Request('POST', 'http://example.com', files=files).prepare().body.decode('ascii'))
--c226ce13d09842658ffbd31e0563c6bd
Content-Disposition: form-data; name="upload_file"; filename="file.txt"


--c226ce13d09842658ffbd31e0563c6bd--

참고 filename="file.txt"매개 변수에 .

files더 많은 제어가 필요한 경우 2-4 개의 요소가 있는 매핑 값에 튜플을 사용할 수 있습니다 . 첫 번째 요소는 파일 이름, 그 뒤에 콘텐츠, 선택적 콘텐츠 유형 헤더 값 및 추가 헤더의 선택적 매핑입니다.

files = {'upload_file': ('foobar.txt', open('file.txt','rb'), 'text/x-spam')}

이것은 선택적 헤더를 제외하고 대체 파일 이름과 콘텐츠 유형을 설정합니다.

다른 필드가 지정되지 않은 파일에서 전체 POST 본문 을 가져 오는 것을 의미하는 경우 files매개 변수를 사용하지 말고 파일을 data. 그런 다음 설정할 수 있습니다 Content-Type아무 것도 그렇지 않으면 설정되지 않습니다으로 너무 헤더를. Python 요청-파일의 POST 데이터를 참조하십시오 .


안녕하세요, 같은 이름을 공유하는 여러 파일을 어떻게 보내나요? 예를 들어 '첨부 파일'과 같습니다.
William Wino

4
@William : 필드 이름을 재사용 할 수있는 2 값 튜플 시퀀스도 사용할 수 있습니다 files = [('attachment', open('attachment1.txt', 'rb')), ('attachment', open('attachment2.txt', 'rb'))].. 각 튜플은 키와 값의 쌍입니다.
Martijn Pieters

2
또한 사용할 수도 files={'file':('nameoffile',open('namoffile','rb'),'Content-Type':'text/html','other header'),'file2':('nameoffile2',open('nameoffile2','rb'),'Content-Type':'application/xml','other header')}있지만 If files = {}가 사용되면 headers = { 'Content-Type': 'blah blah'}를 사용해서는 안됩니다! -> @ martijn-pieters : multipart / form-data Content-Type에는 게시물 본문의 부분을 구분하는 데 사용되는 경계 값이 포함되어야하기 때문입니다. Content-Type 헤더를 설정하지 않으면 요청이 올바른 값으로 설정됩니다.
zaki

1
@MartijnPieters 파일 유출 위험이 없나요? 합니까 requests그것은 가까운?
Matt Messersmith 2019

4
@MattMessersmith : 아니요, 닫히지 않았습니다. 파일을 닫으려면 매핑 에 사용 with open(...) as fobj:하고 사용 fobj하십시오 files.
Martijn Pieters

36

(2018) 새로운 파이썬 요청 라이브러리는이 프로세스를 단순화했습니다. 'files'변수를 사용하여 멀티 파트 인코딩 파일을 업로드하고 싶다는 신호를 보낼 수 있습니다.

url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

r = requests.post(url, files=files)
r.text

3
요청 라이브러리가 파일을 자동으로 닫습니까?
Demetris

1
안녕하세요,이 라이브러리를 사용한 지 오래되었습니다. 좋은 질문. lsof를 입력하여 저와 다른 사람들에게 도움을 줄 수 있습니까? grep "filename"및 결과를 우리와 공유 하시겠습니까? 감사합니다 :)
laycat

1
를 사용하면 lsof파일이 열려있는 것처럼 보이거나 적어도 이것이 다음 결과를 해석하는 방법입니다. 전에 실행하는 open에 기록되지 않은 lsof정보] 테이블 filename. 그런 다음 open이 실행 된 후 read액세스 권한이있는 여러 레코드가 나타납니다 . 를 실행 한 requests.post후에도 파일이 닫히지 않았 음을 나타내는 레코드가 여전히 남아 있습니다.
Demetris

23

클라이언트 업로드

Python requests라이브러리를 사용 하여 단일 파일을 업로드하려는 경우 requests lib 는 스트리밍 업로드를 지원하므로 메모리를 읽지 않고도 대용량 파일 이나 스트림 을 보낼 수 있습니다 .

with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f)

서버 측

그런 다음 server.py메모리에로드하지 않고 스트림을 파일에 저장하도록 파일을 측면에 저장합니다. 다음은 Flask 파일 업로드 를 사용하는 예입니다 .

@app.route("/upload", methods=['POST'])
def upload_file():
    from werkzeug.datastructures import FileStorage
    FileStorage(request.stream).save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    return 'OK', 200

또는 사용 양식 데이터 구문 분석을 WERKZEUG "의 문제에 대한 수정에 언급 한 바와 같이 대용량 파일 업로드가 메모리를 먹는 하기 위해" 대용량 파일 업로드에 비효율적으로 메모리를 사용하지 않도록 ~ 60 초 (일 22 지브 파일을. 메모리 사용량이 일정 정도에있다 13MiB.).

@app.route("/upload", methods=['POST'])
def upload_file():
    def custom_stream_factory(total_content_length, filename, content_type, content_length=None):
        import tempfile
        tmpfile = tempfile.NamedTemporaryFile('wb+', prefix='flaskapp', suffix='.nc')
        app.logger.info("start receiving file ... filename => " + str(tmpfile.name))
        return tmpfile

    import werkzeug, flask
    stream, form, files = werkzeug.formparser.parse_form_data(flask.request.environ, stream_factory=custom_stream_factory)
    for fil in files.values():
        app.logger.info(" ".join(["saved form name", fil.name, "submitted as", fil.filename, "to temporary file", fil.stream.name]))
        # Do whatever with stored file at `fil.stream.name`
    return 'OK', 200

0

우분투에서는 이런 식으로 적용 할 수 있습니다.

특정 위치 (임시)에 파일을 저장 한 다음 열어서 API로 보내기

      path = default_storage.save('static/tmp/' + f1.name, ContentFile(f1.read()))
      path12 = os.path.join(os.getcwd(), "static/tmp/" + f1.name)
      data={} #can be anything u want to pass along with File
      file1 = open(path12, 'rb')
      header = {"Content-Disposition": "attachment; filename=" + f1.name, "Authorization": "JWT " + token}
       res= requests.post(url,data,header)

data변수 의 가치는 무엇 입니까?
am.rez

사용자 이름과 같을 수 있습니다. 방금 REST API에 파일을 업로드하는 방법을 보여
드렸습니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.