I use this GET request https://api.telegram.org/file/bot<token>/<file_path> which allow us to download the file from Telegram API.
Now I need to send this file in the second POST request (form-data).
Right now my code raises such error:
Exception: embedded null byte Traceback
The code snippet:
# Download the file via GET request of the Telegram API.
response = requests.get("{0}/file/bot{1}/{2}".format(TELEGRAM_API_URL, telegram_bot_token, file_path))
files = [
('file', (file_name, open(response.content, 'rb'), 'application/octet-stream')) # error
]
# Upload the file via POST request.
response = requests.post(FILE_STORAGE_SERVICE_API_URL, files=files)
Question:
How do I convert a file correctly so that a POST request can process it?
The data type of the response.content which I take from the first request is <class 'bytes'>.
The working code snippet:
response = requests.get("{0}/file/bot{1}/{2}".format(TELEGRAM_API_URL, telegram_bot_token, file_path))
files = {
"file": response.content
}
requests.post(FILE_STORAGE_SERVICE_API_URL, files=files)
Related
I was trying to upload the file from python script to Laravel backend but it's not getting uploaded to server, event getting the empty array in $request->all() and false in $request->has('file).
Here's the code that I am using.
api.php
Route::post('upload-file', UploadFilesController::class);
UploadFilesController
class UploadFilesController extends Controller
{
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
return response()->json($request->all()); // getting empty error, also used the $request->hasFile('file') and getting false
}
}
Python script
import requests
# Set the API endpoint URL
url = "http://127.0.0.1:8000/api/upload-file"
# Set the file to be uploaded
file_path = "/path/to/file.pdf"
# Set the content type to "multipart/form-data"
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
# Read the file and create the form data
with open(file_path, 'rb') as f:
file_data = {'file': f}
# Send the POST request to the API endpoint
response = requests.post(url, headers=headers, files=file_data)
# Print the response from the server
print(response.text)
I also used the headers = {'Content-Type': 'multipart/form-data'} in place of header and it's also not working.
P.S the same code is working in Insomnia REST
Use headers = {'Content-Type': 'multipart/form-data'}
Try to log request inside laravel itself or use laravel debugger link https://sentry.io/for/laravel/?utm_source=google&utm_medium=cpc&utm_campaign=9779875598&utm_content=g&utm_term=%2Blaravel%20%2Bdebugger&device=m&gclid=CjwKCAiAy_CcBhBeEiwAcoMRHI8g4U4aAptz6YRYwRS7g3fYM8-_AdCE63-YAtSc3QHS9XdEamewuxoCPLQQAvD_BwE&gclid=CjwKCAiAy_CcBhBeEiwAcoMRHI8g4U4aAptz6YRYwRS7g3fYM8-_AdCE63-YAtSc3QHS9XdEamewuxoCPLQQAvD_BwE
I need to upload a file to the system from the API server. post method, the server accepts an authorization token and a file id. I tried to do this by writing to a file(.write(responce.content)), but the text of the saved file is: "Unable to get a response from the server."
code:
import requests
def test_download():
headers = {"Authorization": "token"}
data = {"fileId": "43232-31621-51923-31515-59031"}
responce = requests.post("url/api/integration/file/download",
headers=headers, json=data)
with open("download_file.txt", "wb") as code: code.write(responce.content)
print(responce.text)
assert responce.status_code == 200
but I need the text of the file from the server. is it possible to download the file in another way? thank you in advance)
I want to test a view that is suppose to receive files attached with the request.
my django test:
TEST_DIR = "myapp/tests/test_data/"
file_name = "some_resume.pdf"
email_data = {
"sender": "somedude#someprovidercom",
"recipient": "someotherdude#someotherprovider.com",
"subject": "New candidate",
"stripped-html": "Check out this new candidate."
}
api = APIClient()
with open(FILE_DIR + file_name, "rb") as fp:
response = api.post(
"/api/v1.0/emails/receive/",
data=email_data,
files={"resume": fp}, # pass file handler open with byte mode
format="multipart", # use multipart format
)
print(response)
# test some stuff
the api response is correct: <Response status_code=200, "application/json">
but when I print the files attached to the request in the View I get nothing:
print(request.FILES)
# <MultiValueDict: {}>
I checked everywhere and the format for my api request looks file.
Also, my view works fine when I test with shell sending request with with python requests library.
Am I missing anything? Could id be somehow related to my test environment or some obscure middlewares?
I have a web server that acts as a proxy between users and a file server. Users can upload their files to my web server and I upload them to the file server. I want to be able to do this without saving the temp uploaded file but every time I get unexpected end of file error from the file server. This is my code (I'm using django rest framework for my APIs).
headers = {"content-type":"multipart/form; boundary={}".format(uuid.uuid4().hex)}
files = []
for f in request.FILES.getlist('file'):
files.append((f.name, open(f.file.name,'rb'), f.content_type))
files_dict = {'file': files}
r = requests.post(url, files=files, headers=headers)
You are misusing the content-type header in your request. There is no need to manually set multipart/form and boundary if you're using files argument from requests. That is why you're getting unexpected end of file error. Try sending your request without that header.
r = requests.post(url, files=files)
I am trying to do a curl post query using requests python 2.7, however the API response differently using curl vs. requests lib.
The post query is pretty simple a file and name-value-pair data as the API params.
Below is the curl multipart post request:
curl -uadmin:blabla123 -X POST 127.0.0.1:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/6a0ab661-1c43-43ed-b07f-a564f6bcb5ca/children -F filedata=#file1.txt -F name=document__55;nodeType=content
The python 2.7 code is as below:
import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
from config import USER, PASSWD
def createDocument( documentFilename, documentMetadata, targetFolderNodeId):
'''
Uploads a file and its meta-data to the CMIS server under the specified
target folder
'''
with open(documentFilename, 'rb') as file:
files = {'file': file}
# createURL = 'http://127.0.0.1:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/{0}/children'.format( targetFolderNodeId )
createURL = 'http://127.0.0.1:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/6a0ab661-1c43-43ed-b07f-a564f6bcb5ca/children'
data = {
"name":"document__55",
"nodeType":"cm:content",
}
response = requests.post( createURL, data = data, files = files, auth=HTTPBasicAuth(USER, PASSWD) )
print(response)
print(response.json)
print(response.text)
createDocument('file1.txt', '', '')
Curl returns 200 http code but the script oddly returns 400.
Any help is much appreciate it.
At a first glace the reasons for that script failing vs curl working could be more than one:
nodeType=content in the curl, while "nodeType":"cm:content" in the script
there's an additional comma in the script's payload second line
you're not setting the Content-Type header as multipart/form-data in the script, which curl's -F option actually does
Also, the endpoint should provide a verbose error along with the 400 response. If it does, that could be helpful to identify the error cause.
in fact in the curl I have -F filedata=#file1.txt but in the script I have files = {'file': file} which is not the same so I just had to use files = {'filedata': file} :)
def createDocument( documentFilename, documentMetadata, targetFolderNodeId):
'''
Uploads a file and its meta-data to the CMIS server under the specified
target folder
'''
with open(documentFilename, 'rb') as file:
files = {'filedata': file}
createURL = 'http://127.0.0.1:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/{0}/children'.format( targetFolderNodeId )
data = {
"name":"document__77",
"nodeType":"cm:content"
}
response = requests.post( createURL, data = data, files = files, auth=HTTPBasicAuth(USER, PASSWD) )
print(response)
print(response.json)
print(response.text)
print(response.headers)
# print([i for i in dir(response) if 'header' in i])