akeneo / pim-community-dev

[Community Development Repository] The open source Product Information Management (PIM)
http://www.akeneo.com
Other
956 stars 518 forks source link

I'm reporting a Bug: Badly documented /api/rest/v1/media-files | no existing working examples #18578

Open MPishpecki opened 1 year ago

MPishpecki commented 1 year ago

The documentation for /api/rest/v1/media-files shows no examples of use. In your Postman collection only Curl example works. Python example does not work. I pasted it below to show you what we get as a return.

Is it too much to ask to show us how this call works in any language? No mater how we format the data Akeneo responds with ...You should at least give one of the following properties: \\"product\\" or \\"product_model\\ .

PS: Setting up the connection, obtaining an token and pushing products was walk in the park. This endpoint is the opposite.

Examples of not working calls in Python. (hope this saves someones time)

----------------- Not working ---------------------------- headers = {'Authorization': 'Bearer xxx', 'Content-Type': 'multipart/form-data'} files = { 'product': '"{\"identifier\":\"SKU-001\", \"attribute\":\"Product_images\", \"scope\": null,\"locale\":null}"', 'file': open('/images/01.png', 'rb'), } response = requests.post('{url}/api/rest/v1/media-files', headers=headers, files=files) response.text '{"code":422,"message":"You should at least give one of the following properties: \"product\" or \"product_model\"."}'


import requests

headers = {'Authorization': 'Bearer xxx', 'Content-Type': 'multipart/form-data'} files = { 'product': '{"identifier":"SKU-001", "attribute":"picture", "scope": null,"locale":null}', 'file': open('/images/01.png', 'rb'), }

response = requests.post('{url}/api/rest/v1/media-files', headers=headers, files=files) response.text '{"code":422,"message":"You should at least give one of the following properties: \"product\" or \"product_model\"."}'


-------------------------- this is from your Postman given as an example in Python --------------------------------------

import requests url = "{{url}}/api/rest/v1/media-files" payload={'product': '{"identifier":"SKU-001", "attribute":"picture", "scope": null,"locale":null}'} files=[ ('file',('file',open('/path/to/file','rb'),'application/octet-stream')) ] headers = { 'Authorization': 'Bearer {{token}}', 'Content-Type': 'multipart/form-data' } response = requests.request("POST", url, headers=headers, data=payload, files=files) print(response.text) '{"code":422,"message":"You should at least give one of the following properties: \"product\" or \"product_model\"."}'


EDIT: I tried installing your akeneo_cli and pushing images that way. Here is the code and the result:

AKENEO_URL = "url" AKENEO_CLIENT_ID = "xxx" AKENEO_CLIENT_SECRET = "xxx" AKENEO_USERNAME = "xxx" AKENEO_PASSWORD = "xxx"

from akeneo_cli.client import AkeneoClient akeneo_client = AkeneoClient(AKENEO_URL,AKENEO_CLIENT_ID,AKENEO_CLIENT_SECRET)

with akeneo_client.login(AKENEO_USERNAME, AKENEO_PASSWORD) as session: response = session.put_product_file("SKU-001", "Product_images", "/images/01.png", is_model=False, locale=None, scope=None)

response {'headers': {'Server': 'nginx', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache, private', 'Date': 'Fri, 02 Dec 2022 15:46:29 GMT', 'Location': 'https://akeneo.xxx.hypernode.io/api/rest/v1/media-files/6/3/2/3/63233fc4ccf6cdb053e9affb334208c9f63b722b_01.png', 'Content-Security-Policy': "default-src 'self' .akeneo.com 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'nonce-07f41c14e74157aff6fa6296dac0027c13e46705'; img-src 'self' data: .akeneo.com; frame-src ; font-src 'self' data:; connect-src 'self' .akeneo.com", 'X-Content-Security-Policy': "default-src 'self' .akeneo.com 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'nonce-07f41c14e74157aff6fa6296dac0027c13e46705'; img-src 'self' data: .akeneo.com; frame-src ; font-src 'self' data:; connect-src 'self' .akeneo.com", 'X-WebKit-CSP': "default-src 'self' .akeneo.com 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'nonce-07f41c14e74157aff6fa6296dac0027c13e46705'; img-src 'self' data: .akeneo.com; frame-src ; font-src 'self' data:; connect-src 'self' .akeneo.com"}, 'body': '', 'json': {}}

PhilipKazmeier commented 1 year ago

Hey @MPishpecki , I also spend some time trying to fix that because the error messages are less than optimal...

The thing that fixed it for me in the end was adding all the necessary headers from the formdata to the request. Thanks for the post here pointing out that this is needed.

Simple working NodeJS example:

const formData = new FormData();
let productData = {
    "identifier": "IDENTIFIER", 
    "attribute": "main_image", 
    "scope": null,
    "locale": null
}

formData.append("product", JSON.stringify(productData));
const config = {
    headers: { 
        Authorization: "Bearer xxx",
        ...formData.getHeaders()
    }
}

const fileParts = filePath.split("/"); // to get the filename
formData.append("file", fs.readFileSync(filePath), fileParts[fileParts.length - 1]);

await axios.post(`${this.config.url}/api/rest/v1/media-files`, formData, config);
MPishpecki commented 1 year ago

@PhilipKazmeier thank you for the response. In the end we decided not to use this media-files endpoint. Maybe someone else find this thread useful in the future.

hildickethan commented 1 year ago

Since I came accross this thread while looking for the same thing, after many hours of trying I managed to get this working Python code to create media files on an image attribute (doesn't work for "asset collection" attributes :smiling_face_with_tear:) https://gist.github.com/hildickethan-S73/bdf852d2e73f8fa8ebe2320f45efa787 I post it here for anyone else that stumbles their way here trying to make this endpoint work

this curl was essential for finding my way here, it was from some other issue I can't find right now

curl -X POST -H "Authorization: Bearer {token}" -H "Content-Type: multipart/form-data" -F 'product={"identifier":"123123","attribute":"test_image","scope":null,"locale":null}' -F "file=@/home/x/image.jpeg" "https://domain.com/api/rest/v1/media-files" --trace-ascii /tmp/stdout

You want to use that curl to see how your json is being sent, you need to replicate the "product" with no filename parameter whatsoever (empty, null or "" does not work) and the "file" one needs filename and Content-Type. This needs to be replicated in whatever language you are using

0000: --------------------------d68143a191b92d35
002c: Content-Disposition: form-data; name="product"
005c: 
005e: {"identifier":"123123","attribute":"test_image","scope":null
009e: ,"locale":null}
00af: --------------------------d68143a191b92d35
00db: Content-Disposition: form-data; name="file"; filename="image.jpe
011b: g"
011f: Content-Type: image/jpeg