thelinmichael / spotify-web-api-node

A Node.js wrapper for Spotify's Web API.
http://thelinmichael.github.io/spotify-web-api-node/
MIT License
3.1k stars 497 forks source link

TypeError uploading a playlist cover image #250

Open ohh2ahh opened 5 years ago

ohh2ahh commented 5 years ago

I get the following error when I try to upload a playlist cover image. Authentication is working and the scope contains "playlist-read-private", "playlist-modify-private", "playlist-modify-public", "ugc-image-upload".

TypeError: "string" must be a string, Buffer, or ArrayBuffer
    at Function.byteLength (buffer.js:481:11)
    at Request._end (/Users/user/Desktop/project/node_modules/superagent/lib/node/index.js:804:84)
    at Request.end (/Users/user/Desktop/project/node_modules/superagent/lib/node/index.js:777:15)
    at Object.HttpManager._makeRequest (/Users/user/Desktop/project/node_modules/spotify-web-api-node/src/http-manager.js:85:7)
    at HttpManager.put (/Users/user/Desktop/project/node_modules/spotify-web-api-node/src/http-manager.js:146:15)
    at /Users/user/Desktop/project/node_modules/spotify-web-api-node/src/base-request.js:92:5
    at new Promise (<anonymous>)
    at Request.execute (/Users/user/Desktop/project/node_modules/spotify-web-api-node/src/base-request.js:91:10)
    at SpotifyWebApi.uploadCustomPlaylistCoverImage (/Users/user/Desktop/project/node_modules/spotify-web-api-node/src/spotify-web-api.js:609:8)
    at addCoverToSpotifyPlaylist (/Users/user/Desktop/project/scripts/main.js:131:6)

My code

spotifyApi.uploadCustomPlaylistCoverImage('191...9Ud', '/9j/4AAQSk...KACgAoAKAP//Z')
  .then(
  (data) => { ... },
  (error) => { ... }
);

System

OS: macOS 10.13.6
Node Version: v8.12.0
mikirobles commented 5 years ago

same here!

edit: I ended up implementing my own method for now:

uploadCoverImage: async function (playlistId, accessToken, base64) {
    try {
      return fetch(`https://api.spotify.com/v1/playlists/${playlistId}/images`, {
        method: "PUT", 
        mode: "cors", 
        cache: "no-cache", 
        headers: {
          "Content-Type": "image/jpeg",
          "Authorization": `Bearer ${accessToken}`
        },
        body: base64, // eg. '/9j/....'
      })
    } catch (e) {
      return {error: e}
    }
  },
ab63 commented 5 years ago

Did you fix this? I'm having the same issue.

anderthalb commented 4 years ago

Me too!

Siimone commented 4 years ago

Same here. I tried Spotify route using Postman and I can upload a new cover image but I cannot get any response from Spotify; it changes the cover image but I get an empty string as result. Maybe this empty result causes the crash?

dersimn commented 3 years ago

Apparently the underlying superagent module (used here) does not output much information about this error, this is already part of another PR (see: https://github.com/visionmedia/superagent/issues/1482). This is why the error message is kinda confusing.

tl;dr:

See the diff in my personal repository on how to fix the error: https://github.com/dersimn/spotify-web-api-node/commit/57f14da2aea46bb4ea6dc6fde16c8c41785ef7be

long:

1) Function spotifyApi.uploadCustomPlaylistCoverImage(id, base64) passes the base64 (typeof = string) to WebApiRequest.withBodyParameters(base64) (here)

2) WebApiRequest.withBodyParameters(base64) (here) itself is a call to WebApiRequest._assigner('bodyParameters')(base64) which destructs the String by this for-loop into an object looking like:

{
    '0': 'd',
    '1': 'a',
    '2': 't',
    '3': 'a',
    '4': ':',
    '5': 'i',
    '6': 'm',
    '7': 'a',
    '8': 'g',
    '9': 'e',
    '10': '/',
    '11': 'j',
    '12': 'p',
    '13': 'e',
    '14': 'g',
    '15': ';',
    '16': 'b',
    '17': 'a',
    '18': 's',
    '19': 'e',
    '20': '6',
    '21': '4',
    '22': ',',
    '23': '/',
    '24': '9',
    '25': 'j',
    '26': '/',
    '27': '4',
    '28': 'A',
    '29': 'A',
    '30': 'Q',
    '31': 'S',

Note: My String starts with data:image/jpeg;base64. this is wrong. The Spotify API expects the string to start right with /9j/j/4.... I'm just too lazy to reproduce the error again (I'm happy that I found the issue after 2h or so)..

3) The request with now typeof this.bodyParameters => object ends up in HttpManager (which utilises superagent) and is passed to superagent.send(base64AsFuckedUpObject) and causes the error when superagent.end() is invoked here.