Python Requests: Post JSON and file in single request












23















I need to do a API call to upload a file along with a JSON string with details about the file.



I am trying to use the python requests lib to do this:



import requests

info = {
'var1' : 'this',
'var2' : 'that',
}

data = json.dumps({
'token' : auth_token,
'info' : info,
})

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

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


This throws the following error:



    raise ValueError("Data must not be a string.")
ValueError: Data must not be a string


If I remove the 'files' from the request, it works.

If I remove the 'data' from the request, it works.

If I do not encode data as JSON it works.



For this reason I think the error is to do with sending JSON data and files in the same request.



Any ideas on how to get this working?










share|improve this question

























  • There appears to be a typo in your code: var2 should be followed by a ', right?

    – Christian Ternus
    Oct 18 '13 at 1:14











  • yes, fixed up my example, thanks!

    – oznu
    Oct 18 '13 at 1:18
















23















I need to do a API call to upload a file along with a JSON string with details about the file.



I am trying to use the python requests lib to do this:



import requests

info = {
'var1' : 'this',
'var2' : 'that',
}

data = json.dumps({
'token' : auth_token,
'info' : info,
})

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

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


This throws the following error:



    raise ValueError("Data must not be a string.")
ValueError: Data must not be a string


If I remove the 'files' from the request, it works.

If I remove the 'data' from the request, it works.

If I do not encode data as JSON it works.



For this reason I think the error is to do with sending JSON data and files in the same request.



Any ideas on how to get this working?










share|improve this question

























  • There appears to be a typo in your code: var2 should be followed by a ', right?

    – Christian Ternus
    Oct 18 '13 at 1:14











  • yes, fixed up my example, thanks!

    – oznu
    Oct 18 '13 at 1:18














23












23








23


8






I need to do a API call to upload a file along with a JSON string with details about the file.



I am trying to use the python requests lib to do this:



import requests

info = {
'var1' : 'this',
'var2' : 'that',
}

data = json.dumps({
'token' : auth_token,
'info' : info,
})

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

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


This throws the following error:



    raise ValueError("Data must not be a string.")
ValueError: Data must not be a string


If I remove the 'files' from the request, it works.

If I remove the 'data' from the request, it works.

If I do not encode data as JSON it works.



For this reason I think the error is to do with sending JSON data and files in the same request.



Any ideas on how to get this working?










share|improve this question
















I need to do a API call to upload a file along with a JSON string with details about the file.



I am trying to use the python requests lib to do this:



import requests

info = {
'var1' : 'this',
'var2' : 'that',
}

data = json.dumps({
'token' : auth_token,
'info' : info,
})

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

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


This throws the following error:



    raise ValueError("Data must not be a string.")
ValueError: Data must not be a string


If I remove the 'files' from the request, it works.

If I remove the 'data' from the request, it works.

If I do not encode data as JSON it works.



For this reason I think the error is to do with sending JSON data and files in the same request.



Any ideas on how to get this working?







python json urllib2






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 18 '13 at 1:18







oznu

















asked Oct 18 '13 at 1:11









oznuoznu

9752711




9752711













  • There appears to be a typo in your code: var2 should be followed by a ', right?

    – Christian Ternus
    Oct 18 '13 at 1:14











  • yes, fixed up my example, thanks!

    – oznu
    Oct 18 '13 at 1:18



















  • There appears to be a typo in your code: var2 should be followed by a ', right?

    – Christian Ternus
    Oct 18 '13 at 1:14











  • yes, fixed up my example, thanks!

    – oznu
    Oct 18 '13 at 1:18

















There appears to be a typo in your code: var2 should be followed by a ', right?

– Christian Ternus
Oct 18 '13 at 1:14





There appears to be a typo in your code: var2 should be followed by a ', right?

– Christian Ternus
Oct 18 '13 at 1:14













yes, fixed up my example, thanks!

– oznu
Oct 18 '13 at 1:18





yes, fixed up my example, thanks!

– oznu
Oct 18 '13 at 1:18












5 Answers
5






active

oldest

votes


















17














Don't encode using json.



import requests

info = {
'var1' : 'this',
'var2' : 'that',
}

data = {
'token' : auth_token,
'info' : info,
}

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

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


Note that this may not necessarily be what you want, as it will become another form-data section.






share|improve this answer


























  • If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

    – Arkady
    Apr 9 '15 at 20:03






  • 4





    This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

    – hoefling
    Apr 23 '18 at 9:23











  • Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

    – user565447
    Oct 12 '18 at 15:25











  • @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

    – Bala Krishna
    Feb 13 at 12:48





















9














See this thread How to send JSON as part of multipart POST-request



Do not set the Content-type header yourself, leave that to pyrequests to generate



def send_request():
payload = {"param_1": "value_1", "param_2": "value_2"}
files = {
'json': (None, json.dumps(payload), 'application/json'),
'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
}

r = requests.post(url, files=files)
print(r.content)





share|improve this answer





















  • 1





    Wow.. The None saved me !!!

    – EvgenyKolyakov
    Jun 7 '17 at 11:57











  • let's say Flask is the receiver what would be the way to code flask for that ?

    – MouIdri
    Dec 6 '17 at 16:59






  • 1





    @Mouldri try response.data

    – Dan Salo
    Jan 30 '18 at 20:03






  • 1





    @MouIdri it would be request.form['json']

    – etlds
    Mar 26 at 16:18











  • @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

    – MouIdri
    Mar 27 at 15:53



















2














I'm don't think you can send both data and files in a multipart encoded file, so you need to make your data a "file" too:



files = {
'data' : data,
'document': open('file_name.pdf', 'rb')
}

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





share|improve this answer


























  • How would you decode that? Client would get a python dict not JSON right? it's a question!

    – ivansabik
    Sep 25 '16 at 0:16











  • @sabik: requests encodes the dictionary as form data.

    – RemcoGerlich
    Oct 4 '16 at 8:51



















0














What is more:



files = {
'document': open('file_name.pdf', 'rb')
}


That will only work if your file is at the same directory where your script is.



If you want to append file from different directory you should do:



files = {
'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
}


Where dir_path is a directory with your 'file_name.pdf' file.



But what if you'd like to send multiple PDFs ?



You can simply make a custom function to return a list of files you need (in your case that can be only those with .pdf extension). That also includes files in subdirectories (search for files recursively):



def prepare_pdfs():
return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])


Then you can call it:



my_data = prepare_pdfs()


And with simple loop:



for file in my_data:

pdf = open(file, 'rb')

files = {
'document': pdf
}

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





share|improve this answer































    0














    For sending Facebook Messenger API, I changed all the payload dictionary values to be strings. Then, I can pass the payload as data parameter.



    import requests

    ACCESS_TOKEN = ''

    url = 'https://graph.facebook.com/v2.6/me/messages'
    payload = {
    'access_token' : ACCESS_TOKEN,
    'messaging_type' : "UPDATE",
    'recipient' : '{"id":"1111111111111"}',
    'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
    }
    files = {'filedata': (file, open(file, 'rb'), 'image/png')}
    r = requests.post(url, files=files, data=payload)





    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f19439961%2fpython-requests-post-json-and-file-in-single-request%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      17














      Don't encode using json.



      import requests

      info = {
      'var1' : 'this',
      'var2' : 'that',
      }

      data = {
      'token' : auth_token,
      'info' : info,
      }

      headers = {'Content-type': 'multipart/form-data'}

      files = {'document': open('file_name.pdf', 'rb')}

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


      Note that this may not necessarily be what you want, as it will become another form-data section.






      share|improve this answer


























      • If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

        – Arkady
        Apr 9 '15 at 20:03






      • 4





        This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

        – hoefling
        Apr 23 '18 at 9:23











      • Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

        – user565447
        Oct 12 '18 at 15:25











      • @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

        – Bala Krishna
        Feb 13 at 12:48


















      17














      Don't encode using json.



      import requests

      info = {
      'var1' : 'this',
      'var2' : 'that',
      }

      data = {
      'token' : auth_token,
      'info' : info,
      }

      headers = {'Content-type': 'multipart/form-data'}

      files = {'document': open('file_name.pdf', 'rb')}

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


      Note that this may not necessarily be what you want, as it will become another form-data section.






      share|improve this answer


























      • If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

        – Arkady
        Apr 9 '15 at 20:03






      • 4





        This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

        – hoefling
        Apr 23 '18 at 9:23











      • Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

        – user565447
        Oct 12 '18 at 15:25











      • @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

        – Bala Krishna
        Feb 13 at 12:48
















      17












      17








      17







      Don't encode using json.



      import requests

      info = {
      'var1' : 'this',
      'var2' : 'that',
      }

      data = {
      'token' : auth_token,
      'info' : info,
      }

      headers = {'Content-type': 'multipart/form-data'}

      files = {'document': open('file_name.pdf', 'rb')}

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


      Note that this may not necessarily be what you want, as it will become another form-data section.






      share|improve this answer















      Don't encode using json.



      import requests

      info = {
      'var1' : 'this',
      'var2' : 'that',
      }

      data = {
      'token' : auth_token,
      'info' : info,
      }

      headers = {'Content-type': 'multipart/form-data'}

      files = {'document': open('file_name.pdf', 'rb')}

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


      Note that this may not necessarily be what you want, as it will become another form-data section.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 26 '13 at 7:26

























      answered Nov 26 '13 at 7:20









      proteneerproteneer

      373314




      373314













      • If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

        – Arkady
        Apr 9 '15 at 20:03






      • 4





        This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

        – hoefling
        Apr 23 '18 at 9:23











      • Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

        – user565447
        Oct 12 '18 at 15:25











      • @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

        – Bala Krishna
        Feb 13 at 12:48





















      • If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

        – Arkady
        Apr 9 '15 at 20:03






      • 4





        This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

        – hoefling
        Apr 23 '18 at 9:23











      • Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

        – user565447
        Oct 12 '18 at 15:25











      • @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

        – Bala Krishna
        Feb 13 at 12:48



















      If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

      – Arkady
      Apr 9 '15 at 20:03





      If I do as you suggest, I get another exception: "need more than 1 value to unpack" and wonder what to do with it :-(

      – Arkady
      Apr 9 '15 at 20:03




      4




      4





      This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

      – hoefling
      Apr 23 '18 at 9:23





      This will only work if data are simple key-value pairs (form parameters-like), but all nested stuff will be truncated as HTTP form-encoding is not capable of representing nested data structures.

      – hoefling
      Apr 23 '18 at 9:23













      Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

      – user565447
      Oct 12 '18 at 15:25





      Thanks, @hoefling. You've saved my life. I was trying to understand for 1 hour why the hell that library truncates it (or what was happening).

      – user565447
      Oct 12 '18 at 15:25













      @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

      – Bala Krishna
      Feb 13 at 12:48







      @proteneer This does not seems to be working for me, Doing a call like . d = requests.post('http://localhost:18090/upload',files={ 'face_image': ('mama_justkilled_aman.jpg', open('mama_justkilled_aman.jpg', 'rb'), 'image/jpeg' ) }, data={ 'gffp': 42 }) but data is not being received by the server

      – Bala Krishna
      Feb 13 at 12:48















      9














      See this thread How to send JSON as part of multipart POST-request



      Do not set the Content-type header yourself, leave that to pyrequests to generate



      def send_request():
      payload = {"param_1": "value_1", "param_2": "value_2"}
      files = {
      'json': (None, json.dumps(payload), 'application/json'),
      'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
      }

      r = requests.post(url, files=files)
      print(r.content)





      share|improve this answer





















      • 1





        Wow.. The None saved me !!!

        – EvgenyKolyakov
        Jun 7 '17 at 11:57











      • let's say Flask is the receiver what would be the way to code flask for that ?

        – MouIdri
        Dec 6 '17 at 16:59






      • 1





        @Mouldri try response.data

        – Dan Salo
        Jan 30 '18 at 20:03






      • 1





        @MouIdri it would be request.form['json']

        – etlds
        Mar 26 at 16:18











      • @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

        – MouIdri
        Mar 27 at 15:53
















      9














      See this thread How to send JSON as part of multipart POST-request



      Do not set the Content-type header yourself, leave that to pyrequests to generate



      def send_request():
      payload = {"param_1": "value_1", "param_2": "value_2"}
      files = {
      'json': (None, json.dumps(payload), 'application/json'),
      'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
      }

      r = requests.post(url, files=files)
      print(r.content)





      share|improve this answer





















      • 1





        Wow.. The None saved me !!!

        – EvgenyKolyakov
        Jun 7 '17 at 11:57











      • let's say Flask is the receiver what would be the way to code flask for that ?

        – MouIdri
        Dec 6 '17 at 16:59






      • 1





        @Mouldri try response.data

        – Dan Salo
        Jan 30 '18 at 20:03






      • 1





        @MouIdri it would be request.form['json']

        – etlds
        Mar 26 at 16:18











      • @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

        – MouIdri
        Mar 27 at 15:53














      9












      9








      9







      See this thread How to send JSON as part of multipart POST-request



      Do not set the Content-type header yourself, leave that to pyrequests to generate



      def send_request():
      payload = {"param_1": "value_1", "param_2": "value_2"}
      files = {
      'json': (None, json.dumps(payload), 'application/json'),
      'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
      }

      r = requests.post(url, files=files)
      print(r.content)





      share|improve this answer















      See this thread How to send JSON as part of multipart POST-request



      Do not set the Content-type header yourself, leave that to pyrequests to generate



      def send_request():
      payload = {"param_1": "value_1", "param_2": "value_2"}
      files = {
      'json': (None, json.dumps(payload), 'application/json'),
      'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
      }

      r = requests.post(url, files=files)
      print(r.content)






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited May 23 '17 at 11:47









      Community

      11




      11










      answered Mar 11 '16 at 18:04









      ralf htpralf htp

      4,20021122




      4,20021122








      • 1





        Wow.. The None saved me !!!

        – EvgenyKolyakov
        Jun 7 '17 at 11:57











      • let's say Flask is the receiver what would be the way to code flask for that ?

        – MouIdri
        Dec 6 '17 at 16:59






      • 1





        @Mouldri try response.data

        – Dan Salo
        Jan 30 '18 at 20:03






      • 1





        @MouIdri it would be request.form['json']

        – etlds
        Mar 26 at 16:18











      • @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

        – MouIdri
        Mar 27 at 15:53














      • 1





        Wow.. The None saved me !!!

        – EvgenyKolyakov
        Jun 7 '17 at 11:57











      • let's say Flask is the receiver what would be the way to code flask for that ?

        – MouIdri
        Dec 6 '17 at 16:59






      • 1





        @Mouldri try response.data

        – Dan Salo
        Jan 30 '18 at 20:03






      • 1





        @MouIdri it would be request.form['json']

        – etlds
        Mar 26 at 16:18











      • @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

        – MouIdri
        Mar 27 at 15:53








      1




      1





      Wow.. The None saved me !!!

      – EvgenyKolyakov
      Jun 7 '17 at 11:57





      Wow.. The None saved me !!!

      – EvgenyKolyakov
      Jun 7 '17 at 11:57













      let's say Flask is the receiver what would be the way to code flask for that ?

      – MouIdri
      Dec 6 '17 at 16:59





      let's say Flask is the receiver what would be the way to code flask for that ?

      – MouIdri
      Dec 6 '17 at 16:59




      1




      1





      @Mouldri try response.data

      – Dan Salo
      Jan 30 '18 at 20:03





      @Mouldri try response.data

      – Dan Salo
      Jan 30 '18 at 20:03




      1




      1





      @MouIdri it would be request.form['json']

      – etlds
      Mar 26 at 16:18





      @MouIdri it would be request.form['json']

      – etlds
      Mar 26 at 16:18













      @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

      – MouIdri
      Mar 27 at 15:53





      @DanSalo thanks, i forgot to answer, I did find it a will. thanks for your confirmation ( upvoted your comments )

      – MouIdri
      Mar 27 at 15:53











      2














      I'm don't think you can send both data and files in a multipart encoded file, so you need to make your data a "file" too:



      files = {
      'data' : data,
      'document': open('file_name.pdf', 'rb')
      }

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





      share|improve this answer


























      • How would you decode that? Client would get a python dict not JSON right? it's a question!

        – ivansabik
        Sep 25 '16 at 0:16











      • @sabik: requests encodes the dictionary as form data.

        – RemcoGerlich
        Oct 4 '16 at 8:51
















      2














      I'm don't think you can send both data and files in a multipart encoded file, so you need to make your data a "file" too:



      files = {
      'data' : data,
      'document': open('file_name.pdf', 'rb')
      }

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





      share|improve this answer


























      • How would you decode that? Client would get a python dict not JSON right? it's a question!

        – ivansabik
        Sep 25 '16 at 0:16











      • @sabik: requests encodes the dictionary as form data.

        – RemcoGerlich
        Oct 4 '16 at 8:51














      2












      2








      2







      I'm don't think you can send both data and files in a multipart encoded file, so you need to make your data a "file" too:



      files = {
      'data' : data,
      'document': open('file_name.pdf', 'rb')
      }

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





      share|improve this answer















      I'm don't think you can send both data and files in a multipart encoded file, so you need to make your data a "file" too:



      files = {
      'data' : data,
      'document': open('file_name.pdf', 'rb')
      }

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






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Oct 18 '13 at 1:41

























      answered Oct 18 '13 at 1:28









      AChampionAChampion

      21.7k32346




      21.7k32346













      • How would you decode that? Client would get a python dict not JSON right? it's a question!

        – ivansabik
        Sep 25 '16 at 0:16











      • @sabik: requests encodes the dictionary as form data.

        – RemcoGerlich
        Oct 4 '16 at 8:51



















      • How would you decode that? Client would get a python dict not JSON right? it's a question!

        – ivansabik
        Sep 25 '16 at 0:16











      • @sabik: requests encodes the dictionary as form data.

        – RemcoGerlich
        Oct 4 '16 at 8:51

















      How would you decode that? Client would get a python dict not JSON right? it's a question!

      – ivansabik
      Sep 25 '16 at 0:16





      How would you decode that? Client would get a python dict not JSON right? it's a question!

      – ivansabik
      Sep 25 '16 at 0:16













      @sabik: requests encodes the dictionary as form data.

      – RemcoGerlich
      Oct 4 '16 at 8:51





      @sabik: requests encodes the dictionary as form data.

      – RemcoGerlich
      Oct 4 '16 at 8:51











      0














      What is more:



      files = {
      'document': open('file_name.pdf', 'rb')
      }


      That will only work if your file is at the same directory where your script is.



      If you want to append file from different directory you should do:



      files = {
      'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
      }


      Where dir_path is a directory with your 'file_name.pdf' file.



      But what if you'd like to send multiple PDFs ?



      You can simply make a custom function to return a list of files you need (in your case that can be only those with .pdf extension). That also includes files in subdirectories (search for files recursively):



      def prepare_pdfs():
      return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])


      Then you can call it:



      my_data = prepare_pdfs()


      And with simple loop:



      for file in my_data:

      pdf = open(file, 'rb')

      files = {
      'document': pdf
      }

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





      share|improve this answer




























        0














        What is more:



        files = {
        'document': open('file_name.pdf', 'rb')
        }


        That will only work if your file is at the same directory where your script is.



        If you want to append file from different directory you should do:



        files = {
        'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
        }


        Where dir_path is a directory with your 'file_name.pdf' file.



        But what if you'd like to send multiple PDFs ?



        You can simply make a custom function to return a list of files you need (in your case that can be only those with .pdf extension). That also includes files in subdirectories (search for files recursively):



        def prepare_pdfs():
        return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])


        Then you can call it:



        my_data = prepare_pdfs()


        And with simple loop:



        for file in my_data:

        pdf = open(file, 'rb')

        files = {
        'document': pdf
        }

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





        share|improve this answer


























          0












          0








          0







          What is more:



          files = {
          'document': open('file_name.pdf', 'rb')
          }


          That will only work if your file is at the same directory where your script is.



          If you want to append file from different directory you should do:



          files = {
          'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
          }


          Where dir_path is a directory with your 'file_name.pdf' file.



          But what if you'd like to send multiple PDFs ?



          You can simply make a custom function to return a list of files you need (in your case that can be only those with .pdf extension). That also includes files in subdirectories (search for files recursively):



          def prepare_pdfs():
          return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])


          Then you can call it:



          my_data = prepare_pdfs()


          And with simple loop:



          for file in my_data:

          pdf = open(file, 'rb')

          files = {
          'document': pdf
          }

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





          share|improve this answer













          What is more:



          files = {
          'document': open('file_name.pdf', 'rb')
          }


          That will only work if your file is at the same directory where your script is.



          If you want to append file from different directory you should do:



          files = {
          'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
          }


          Where dir_path is a directory with your 'file_name.pdf' file.



          But what if you'd like to send multiple PDFs ?



          You can simply make a custom function to return a list of files you need (in your case that can be only those with .pdf extension). That also includes files in subdirectories (search for files recursively):



          def prepare_pdfs():
          return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])


          Then you can call it:



          my_data = prepare_pdfs()


          And with simple loop:



          for file in my_data:

          pdf = open(file, 'rb')

          files = {
          'document': pdf
          }

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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 28 '16 at 12:47









          tc_qatc_qa

          112




          112























              0














              For sending Facebook Messenger API, I changed all the payload dictionary values to be strings. Then, I can pass the payload as data parameter.



              import requests

              ACCESS_TOKEN = ''

              url = 'https://graph.facebook.com/v2.6/me/messages'
              payload = {
              'access_token' : ACCESS_TOKEN,
              'messaging_type' : "UPDATE",
              'recipient' : '{"id":"1111111111111"}',
              'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
              }
              files = {'filedata': (file, open(file, 'rb'), 'image/png')}
              r = requests.post(url, files=files, data=payload)





              share|improve this answer




























                0














                For sending Facebook Messenger API, I changed all the payload dictionary values to be strings. Then, I can pass the payload as data parameter.



                import requests

                ACCESS_TOKEN = ''

                url = 'https://graph.facebook.com/v2.6/me/messages'
                payload = {
                'access_token' : ACCESS_TOKEN,
                'messaging_type' : "UPDATE",
                'recipient' : '{"id":"1111111111111"}',
                'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
                }
                files = {'filedata': (file, open(file, 'rb'), 'image/png')}
                r = requests.post(url, files=files, data=payload)





                share|improve this answer


























                  0












                  0








                  0







                  For sending Facebook Messenger API, I changed all the payload dictionary values to be strings. Then, I can pass the payload as data parameter.



                  import requests

                  ACCESS_TOKEN = ''

                  url = 'https://graph.facebook.com/v2.6/me/messages'
                  payload = {
                  'access_token' : ACCESS_TOKEN,
                  'messaging_type' : "UPDATE",
                  'recipient' : '{"id":"1111111111111"}',
                  'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
                  }
                  files = {'filedata': (file, open(file, 'rb'), 'image/png')}
                  r = requests.post(url, files=files, data=payload)





                  share|improve this answer













                  For sending Facebook Messenger API, I changed all the payload dictionary values to be strings. Then, I can pass the payload as data parameter.



                  import requests

                  ACCESS_TOKEN = ''

                  url = 'https://graph.facebook.com/v2.6/me/messages'
                  payload = {
                  'access_token' : ACCESS_TOKEN,
                  'messaging_type' : "UPDATE",
                  'recipient' : '{"id":"1111111111111"}',
                  'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
                  }
                  files = {'filedata': (file, open(file, 'rb'), 'image/png')}
                  r = requests.post(url, files=files, data=payload)






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 29 '18 at 17:16









                  wannikwannik

                  8,30363453




                  8,30363453






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f19439961%2fpython-requests-post-json-and-file-in-single-request%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      List item for chat from Array inside array React Native

                      Thiostrepton

                      Caerphilly