Support Topics Documentation Slack YouTube Blog

Rest API: Upload file with Python

I upload an image using Rest API with python. It response 200 and fileURL. The folder was created but the image was not created. I tried curl, it works fine. Have any idea?

Make sure to compare the request made by your Python code with the one from curl. If an image is not created, there must be something missing in the request.

Regards,
Mark

Removed comment

Here’s a sample of curl from the documentation:

http://support.backendless.com/public/attachments/d1f5757fbea63ba510d1131fabfa5ea4.png</img>
Notice the Content-Type header, it is “multipart/form-data”. In your code is “application/json”. There is also the “–form” argument. I assume “requests.post” in Python handles it, but I am not sure. So hopefully it is just the Content-Type…

Regards,
Mark

d1f5757fbea63ba510d1131fabfa5ea4.png

headers={
"content-type":"application/json", 
"application-id":"myID", 
"secret-key":"myKey", 
"application-type":"REST" 
} 
coverPhotoUrl = "[url=http://api.backendless.com/v1/files/restaurantCoverphotos/coverphoto.jpg]http://api.backendless.com/v1/files/restaurantCoverphotos/coverphoto.jpg"[/url]; 
files = {'file': ("coverphoto.jpg", open('coverphoto.jpg', 'rb'))} 
resp = requests.post(coverPhotoUrl, files=files, headers = headers) 
print(resp.status_code) 
print(rep.text)

The code is fairly simple, please help take a look! Thanks!

No, it was not the problem. I used multipart/form-data and it did not work. I changed to application/json because I saw there was a line in the documentation as below. It is better to update the documentation too.

Content-Type - a static value, should be set to application/json. This header is mandatory.

I used the curl command exactly as in the documentation and file upload is working just fine. The documentation is correct in this case.

Yes I know, as I said in the problem description. But it is not working for Python. I have one to many relation object to upload. The amount is quite big, thus I am going to use Python to do so because curl is not that convenient for my case.

One to many relation object to upload? I thought you said you are uploading files? What does it have to do with objects? :slight_smile:

File upload and saving objects are two completely different API calls…

Finally it works with Python. Without using requests, I change to pycurl, it works well.


import pycurl
import time


curr_time = int(time.time())


file_name = "coverphoto_" + str(curr_time) + ".jpg"
c = pycurl.Curl()
c.setopt(c.URL, 'http://api.backendless.com/v1/files/coverphotos/' + file_name)


c.setopt(c.HTTPPOST, [
    ('fileupload', (
        # upload the contents of this file
        c.FORM_FILE, 'image.jpg',
        # specify a different file name for the upload
        c.FORM_FILENAME, file_name,
        # specify a different content type
        c.FORM_CONTENTTYPE, 'image/jpg',
    )),
])
c.setopt(pycurl.HTTPHEADER, ['content-type: multipart/form-data',
                                          'application-id: myId',
                                          'secret-key:myKey',
                                          'application-type:REST'])
c.perform()
c.close()

Weinan, you rock! I am glad you got it working.

Cheers,
Mark

Encountered the same issue, whereby the call would return a URL but no file was uploaded. Managed to get it working with Python Requests by not specifying “Content-Type” from the header.

Have not explored why this is so, but I guess Requests handles the “Content-Type”. If I do manually specify “multipart/form-data” and pass to Requests it does not work.

The code I am using is a follows

url = 'http://api.backendless.com/v1/files/media/poster/' + filename
file = {'upload': (filename, open(filename, 'rb'), 'image/jpg')}
header = {"application-id": appID, "secret-key": restKey, "application-type": "REST"}
r = requests.post(url, files=file, headers=header)

Adrian,

When content-type is “multipart/form-data”, is the body of the request structured accordingly to the rules of multipart request?

Regards,
Mark

Hi Mark.

I believe it should be. I am only getting into some development with Python and first time I am making use of Requests, so don’t quote me on that. Essentially, the code that wasn’t working is exactly the same posted, except for inclusion of “Content-Type”.

Like so:

header = {"application-id": appID, "secret-key": restKey, "application-type": "REST", "content-type": "multipart/form-data"}

The code above when passed to Requests would create the error where fileURL is return but no file is uploaded. This case seems to be unique to how Requests handles it, as opposed to say PyCurl which as posted here works/requires “Content-Type”.

Also, see the same problem of receiving a 200 and a FileURL but the file doesn’t exist in the console.

I just tried the CURL command shown as an example here:

https://backendless.com/documentation/files/rest/files_file_upload.htm

and the upload worked just fine. If you do not see a file after the upload, check the request, there is got to be an error in it.

Regards,
Mark

Above given Programming coding are nice,i tried this codes i have an lot of errors.

https://www.besanttechnologies.com/python-training-in-rajaji-nagar-bangalore

Why do I need to provide a file name for Backendless in two places, in the url itself and the body as part of formData? It makes no sense. Do you have a REST point that does not require a filename in the URL itself?

Thanks.

the body part of form-data can be any identifier, it doesn’t have to be file name. We require file name only in the URL of the request:
https://backendless.com/docs/rest/files_file_upload.html

I get it. It is the worse option of the two. With this setup it appears not possible (as far as I understand at the moment) to simply do loopover { formData.append('fileToUpload[]", fileObject, filename) } and have your endpoint extract the filenames and do the right thing without having names in the URLs, when a fetch is performed.

formData.append has two versions, one of them takes a third parameter.i.e. a file name.