getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.9k stars 1.56k forks source link

Sentry.captureFeedback produces unviewable images in sentry.io #12599

Closed Saturate closed 3 months ago

Saturate commented 3 months ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

8.9.2

Framework Version

nextjs 14.2.2

Link to Sentry event

https://impact-as-01.sentry.io/feedback/?feedbackSlug=dagrofa-spa:1699972&project=4507299065954384

SDK Setup

No response

Steps to Reproduce

We are using the Feedback API to submit user feedback, we tried adding support for uploading images, however these do not show up correctly in Sentry.

We are converting a file to base 64 with a function like this that uses FileReader

 const convertBase64 = (file: File) => {
    return new Promise((resolve, reject) => {
      const fileReader = new FileReader();
      fileReader.onload = () => {
        resolve(fileReader.result);
      };
      fileReader.onerror = (error) => {
        reject(error);
      };
      fileReader.readAsDataURL(file);
    });
  };

It ends up like this string (concatinated):

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE....AHwAAAQ9k=

This works file when trying to view it with <img src="data-here" /> but it's not working in sentry. I'm suspecting that the docs on https://docs.sentry.io/platforms/javascript/user-feedback/#user-feedback-api is not 100% clear on the base64 expected.

Expected Result

Getting a image that's viewable in sentry.

Actual Result

Broken image. Screenshot 2024-06-21 at 13 37 04

ryan953 commented 3 months ago

@Saturate It seems like the fileReader.readAsDataURL call isn't compatible with our attachments backend. What sentry.io is doing is putting a url into the src attribute so we can fetch the image data when it's needed and not have to stuff the image data into ajax response payloads. The data-url bytes aren't inserted into the page directly, if they were then <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE....AHwAAAQ9k=" /> would work.

I spent some time reviewing the Feedback documentation related to this and made some updates to this page: https://docs.sentry.io/platforms/javascript/user-feedback/configuration/

Specifically for your case checkout the "Bring your own widget" section. We've added an HTML+JavaScript example which shows how you can use an <input> tag to read the image data and pass it into the captureFeedback() function. The crux of it is const data = new Uint8Array(await attatchmentField.arrayBuffer());

It's not the most beautiful snippet of javascript, but it will get the job done. I think the reason we accept data in this format is a mix of historical context, and because it's possible to get data into this format no matter what language/platform the SDK is written in.

I hope that snippet helps! Since you've got a file: File parameter for your function then you should be able to tweak the example with a call to file.readAsArrayBuffer() instead of await attatchmentField.arrayBuffer(). The MDN docs are here: readAsArrayBuffer().

ryan953 commented 3 months ago

I'm going to close this ticket, but if you have any followup questions open it back up and let me know!

Saturate commented 3 months ago

Thanks @ryan953 that helps :) just needed to know the data format to send.