Announcements

Help Wizard

Step 1

NEXT STEP

FAQs

Please see below the most popular frequently asked questions.

Loading article...

Loading faqs...

VIEW ALL

Ongoing Issues

Please see below the current ongoing issues which are under investigation.

Loading issue...

Loading ongoing issues...

VIEW ALL

Add Custom Playlist Cover Image not working

Add Custom Playlist Cover Image not working

Plan

Premium

Country

United States

 

Device

MacBook Pro M1 Pro 14-inch 2021

Operating System

macOS Ventura 13.3

 

I've been trying for several days now to unearth how in the world the Add Custom Playlist Cover Image endpoint works. The documentation is horrible at best, so I took to Google to see if I could solve my problem. I couldn't...

 

Every check and balance that I found has been properly checked and balanced, and I even tried using multiple coding languages. Ultimately I'd like this to be part of a personal React project, and I'm using Axios. But I've also tried using PHP within WordPress as well, just to see if the call needs to be made server-side instead of browser-side.

 

All attempts result in a 400 "Bad request" error from Spotify:

 

{
  "error" : {
    "status" : 400,
    "message" : "Bad request."
  }
}

 

 

My PHP (using the WordPress built-in wp_remote_request function) was thrown together for testing, but it should work (I tested other Spotify endpoints with luck):

 

// Print out the image on the screen to prove the base64 code is legit.
echo '<img src="data&colon;image/jpeg;base64,'.$_POST['base64image'].'" />';
			$body = $_POST['base64image'];
			$args = array(
			    'headers' => array(
			    	'Authorization'		=> "Bearer {$_POST['authKey']}", // This is just a test, so I'm just pasting the most recent auth code in a form field to send it along here.
				    'Content-Type'   	=> 'image/jpeg',
			    ),
			    'body'      => $body,
			    'method'    => 'PUT'
			);
// Make use of the built-in WordPress wp_remote_request function. All $_POST params are valid.
			$result =  wp_remote_request( "https://api.spotify.com/v1/playlists/{$_POST['playlistId']}/images", $args );
// Print the result and hope to god there's no 400 error!
			echo '<pre>'.print_r( $result, true ).'</pre>';

 

 

I added the <img/> tag there just to prove that the base64 image code is legit and it does, in fact, result in an image preview.

 

And in React/Axios the code looks like this:

 

// Some revised code I found on Stack Overflow I think...
const getFileBase64 = file => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve({ file: reader.result, type: file.type });
    reader.onerror = error => resolve({ file: null, error });
});

export function uploadPlaylistImage(file,playlistId) {
// All logs look fine. The file is being added with react-dropzone
  console.log( 'file', file[0] )
  console.log( 'playlistId', playlistId )

  const getBase64CoverThenUpload = async (file) => {
    const base64cover = await getFileBase64(file)
    console.log( 'base64cover', base64cover )
// Forgive my lack of error catching, this is preliminary. Plus it's a personal project so it'll never see the light of day ;)
    if( base64cover.file ) {
      const bytesNoMetadata = base64cover.file.replace('data:', '').replace(/^.+,/, '')
      return axios.put(PLAYLIST_IMAGES.replace( '{playlist_id}', playlistId ), bytesNoMetadata, {
          headers: { 
            'Content-Type': base64cover.type // I'm only upload JPGs so this will always be "image/jpeg"
          }
      }).then(async (data) => {
        console.log( data.data )
        return { ...data.data };
      })
    }
  }
  getBase64CoverThenUpload( file[0] )
}

 

I didn't implement any error catching yet, and the Authorization header with the Bearer token is set up in the request interceptor, so everything that needs to be sent to the endpoint is sent in a nice clean package.  PLAYLIST_IMAGES is a constant with the correct path. All of the console logging I'm doing shows the expected data.

 

Checks & Balances that I've researched not only on this board but other boards/articles while Googling this:

  1. The body is the raw base64 code, without the prefix "data&colon;image/jpeg; base64,"
  2. The base64 code is 17K, way less than the supposed (yet undocumented) 256K limit.
  3. The base64 has no line breaks, no white spaces, no extra characters.
  4. Tried all combinations of Binary, UTF-8, ASCII, UTF-16 charsets, with base64URL (URL-safe encoding) enabled and disabled.
  5. The Playlist ID is correct, and I've tried several, all of which are my own playlists. I've tried with public ones and private ones to boot.
  6. 'Content-Type' header is always 'image/jpeg'
  7. Auth scopes for the Authorization token include all mandatory scopes for this endpoint: ugc-image-upload playlist-modify-public playlist-modify-private

And to reiterate that I've tried several ways to hit this endpoint:

  1. Browser-side using React/Axios
  2. Server-side using PHP/WordPress
  3. Postman (didn't mention this above, but screenshot attached with playlist ID hidden)

Final thought: My app status is (and will remain in) Development Mode. Would this be problematic?

 

I'm hoping there's someone out there that can help me understand what I am doing wrong. I'd also like to know if anyone actually has gotten this endpoint to work, and what the secret sauce is, because I'm at my wit's end. Thanks to everyone!

Screenshot 2023-04-04 at 10.19.27 AM.png
Reply
0 Replies

Suggested posts

Type a product name