Image gets uploaded to Media but not with proper content type

I have been successfully uploading PDFs using similar code below but not sure why it does not work if I try to upload images they look like this

Here is my Python code

import requests,json

h = {
'X-Api-Version': '3',
'Authorization': 'Bearer ABC',
'Accept': 'application/json',
'Content-Type': 'application/json'
}

image_file=requests.get('https://upload.wikimedia.org/wikipedia/commons/c/c6/Kimi_Raikkonen_2006_test.jpg', 
                      stream=True).content

upload_requests = json.loads(requests.post("https://site-api.datocms.com/upload-requests", headers=h, data=json.dumps({
  "data": {
    "type": "upload_request",
    "attributes": {
      "filename": "Kimi_Raikkonen_2006_test.jpg",
    }
  }
})).text)

print(upload_requests)

requests.put(upload_requests['data']['attributes']['url'], files={'file': image_file}).text

final_upload_resp = requests.post("https://site-api.datocms.com/uploads", headers=h, data=json.dumps({
  "data": {
    "type": "upload",
    "attributes": {
      "path": upload_requests['data']['id'],
      "author": "Me",
      "copyright": "2020 DatoCMS",
      "default_field_metadata": {
        "en": {
          "alt": "Test",
          "title": "Test",
          "custom_data": {}
        }
      }
    }
  }
})).text

final_upload_resp = json.loads(final_upload_resp)
print(final_upload_resp)
if final_upload_resp['data']['type'] == "job":
    final_upload_resp = json.loads(requests.get("https://site-api.datocms.com/job-results/%s" % final_upload_resp['data']['id'], headers=h).text)

requests.get("https://site-api.datocms.com/job-results/upload_id/%s"%(final_upload_resp['data']['id']), headers=h).text

As I said, file gets uploaded to Media and correct size, but it does not have proper content type

hello @mohammadayub6565 and welcome to Community!

Are you sure that the image that you are uploading is not corrupted? Can you please share the picture here after you have downloaded?

@mat_jack1

This is real image url as also shown in my question

Here is the download url of the image that actually got to dato after I ran my code, I have tried other images as well, I get same results each time

@mohammadayub6565 sorry I’m not a Python expert, but looks like you are not downloading the image correctly with requests. I’m not sure why though :frowning:

If you are still stuck with this please get in touch, I might try to spend some more time on this tomorrow.

I should have also mentioned that I also tried to upload image file by reading directly from my computer

requests.put(upload_requests['data']['attributes']['url'], files={'file': open('image.jpg', 'rb')}).text

That did not work too, but at the same time, uploading PDF file works perfectly :frowning:

Hey @mohammadayub6565! Just found the issue!

Using requests.put() with the files parameter sends a multipart/form-data encoded request which is not what you should do. As the docs says:

Use the obtained URL to perform a PUT request directly to AWS, uploading the raw content of the file as the request body;

Here’s a corrected version of your script:

import requests,json

h = {
'X-Api-Version': '3',
'Authorization': 'Bearer API-TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json'
}

image_file=requests.get('https://upload.wikimedia.org/wikipedia/commons/c/c6/Kimi_Raikkonen_2006_test.jpg',
                      stream=True).content

upload_requests = json.loads(requests.post("https://site-api.datocms.com/upload-requests", headers=h, data=json.dumps({
  "data": {
    "type": "upload_request",
    "attributes": {
      "filename": "Kimi_Raikkonen_2006_test.jpg",
    }
  }
})).text)

print(upload_requests)

requests.put(upload_requests['data']['attributes']['url'], data=image_file).text

final_upload_resp = requests.post("https://site-api.datocms.com/uploads", headers=h, data=json.dumps({
  "data": {
    "type": "upload",
    "attributes": {
      "path": upload_requests['data']['id'],
      "author": "Me",
      "copyright": "2020 DatoCMS",
      "default_field_metadata": {
        "en": {
          "alt": "Test",
          "title": "Test",
          "custom_data": {}
        }
      }
    }
  }
})).text

final_upload_resp = json.loads(final_upload_resp)

print(final_upload_resp)

if final_upload_resp['data']['type'] == "job":
    while True:
      response = requests.get("https://site-api.datocms.com/job-results/%s" % final_upload_resp['data']['id'], headers=h)
      print(response)

      if response.status_code == 200:
          print(response.text)
          final_upload_resp = json.loads(response.text)
          upload = final_upload_resp['data']['attributes']['payload']['data']
          print(upload)
          break

Hi, i need the same example but in javascript.

Hi, i have the same problem, but in javascript, i didnt understand how i upload the raw content of the file. Do you have a example in javascript ? My image comes from a input type file.

Hello @problemchild007m

To upload a file using JavaScript you can do the following request using the Node client: Create a new upload - Upload - Content Management API
If you are still having problems creating an upload with the node client, send the snippet over so we can see what could be going wrong :slight_smile:

Hello,
Im doing using the HTTP verbs on Vanilla JS, but i dont know what i put on the body of the Step 2, Create a new upload - Upload - Content Management API. I need a example on Vanilla JS,

const uploadToStoreBucket = async (file) => {
  const storeBucketUrl = await uploadRequest()
  console.log(storeBucketUrl.data.attributes.url)
  fetch(storeBucketUrl.data.attributes.url, {
    method: 'PUT',
    body: 
  })
}

Im using a input type file, so what is the content of body HTTP request ?

I Tried to use the upload in the browser, but i got an error on onProgress,
Capturar
This is my code: `const client = new Dato.SiteClient(token);

async function createUpload(file) {
const path = await client.createUploadPath(file);
const upload = await client.uploads.create({
path,
author: ‘Matheus’,
copyright: ‘Copyright’,
defaultFieldMetadata: {
en: {
alt: ‘Teste’,
title: ‘title padrao’,
},
},
});
return upload
}
productImage.addEventListener(‘change’, async (event) => {
const file = event.target.files[0];
createUpload(file).then((upload) => console.log(upload))
});`

html: <script src="https://unpkg.com/datocms-client@latest/dist/client.js"></script>

@problemchild007m

I’m assuming you want to use vanilla JS and not the Node client because you are trying to do the requests on the server-side?

Doing the API requests directly on the client side is not recommended, as you haver to provide the authToken to do requests. You can think of it as doing a database request directly from the client-side, you’d have to provide the client with credentials, which is not a good idea.

To streamline the process, you should be using our node-client, that can make requests effortlessly on the server-side (securely) Using the NodeJS client - DatoCMS

Ok, i tried to upload in the browser, using the script tag <script src="https://unpkg.com/datocms-client@latest/dist/client.js"></script>, but doesnt work too.

Thats because you can’t read your local machine files from the browser, you need to do this from a NodeJS script, not using javascript in the browser