Nicholas Goldstein
Nicholas Goldstein

Reputation: 25

Trying to Retrieve an Image from Digital Ocean Spaces Using a Presigned URL in Flutter, Golang for Backend

I've been working on this problem for a while. There seems to be an error with the Flutter side of things, since I can access the file directly from the presigned URL that I generated on the backend. I've tried a number of different things, the latest being downloading the image using the http package and then attempting to display it, but I always get this error:

════════ Exception caught by image resource service ════════════════════════════ The following _Exception was thrown resolving an image frame: Exception: Codec failed to produce an image, possibly due to invalid image data.

For context, I've included the Go and Flutter code below:

Like I mentioned above, the Go portion of the code seems to work.


func FetchPresignedURL(c *gin.Context) {
    sess := session.Must(session.NewSession(&aws.Config{
        Credentials: credentials.NewStaticCredentials(os.Getenv("DO_SPACES_ACCESS_KEY"), os.Getenv("DO_SPACES_SECRET_KEY"), ""),
        Endpoint:    aws.String(os.Getenv("DO_SPACES_ENDPOINT")),
        Region:      aws.String(os.Getenv("DO_SPACES_REGION")),
    }))

    svc := s3.New(sess)

    req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
        Bucket: aws.String(os.Getenv("DO_SPACES_BUCKET")),
        Key:    aws.String(c.Query("file_path")),
    })

    //Presign for an hour
    urlStr, err := req.Presign(7 * 24 * time.Hour)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "error": "Failed to generate presigned URL",
        })
        return
    }

    c.JSON(http.StatusOK, gin.H{
        "url": urlStr,
    })
}

There must be something in the way that I'm trying to use the image in Flutter that is causing this error:


  Future<ImageProvider> loadImage(String url) async {
    try {
      final response = await http.get(Uri.parse(url));
      if (response.statusCode == 200) {
        return MemoryImage(response.bodyBytes);
      } else {
        print('Failed to load image: HTTP status code ${response.statusCode}');
        throw Exception('Failed to load image');
      }
    } catch (e) {
      print('Failed to load image: $e');
      throw Exception('Failed to load image');
    }
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((_) async {
      showLoading(context);
      ...
        String? presignedURL = await HandleFetchPresignedURL(context, user.pic);
        if (presignedURL == null) {
          ShipErrorToUI(context, "Error loading profile picture");
        } else {
          try {
            final imageProvider = await loadImage(presignedURL);
            setState(() {
              pic = imageProvider;
            });
          } catch (e) {
            print('Failed to load image: $e');
          }
        }
        print(
            "${name} - ${intro} - ${dob} - ${pic} - ${selectedCountry} - ${selectedLocation}");
      } else {
        ShipErrorToUI(context, "There was an error fetching user data");
      }
      hideLoading(context);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ...
        SizedBox(height: 16.0),
        Container(
          child: pic != null ? Image(image: pic!) : Text('No image available'),
        ),
        ...

Upvotes: 1

Views: 77

Answers (0)

Related Questions