How to effectively utilize signed requests for AWS S3 when uploading images?

My project involves developing a react native application similar to Slack, and I'm currently facing an issue with image uploads to S3.

I decided to use the getSignedUrl route for this functionality.

The process goes as follows: the client selects a photo, fetches a signed URL from the bucket, then updates the URL on the server for that specific user. Finally, a PUT request is made to the signed URL that was obtained.

Most of the time, everything works smoothly - the files end up in the correct bucket, and they are indeed photos. However, there are two main issues:

A) When clicking the link, the file gets downloaded instead of being displayed in the browser.

B) The file turns out to be an XML file rather than an image, and can only be opened in software like Photoshop.

I've attempted various solutions such as adjusting the data.append type, adding headers to the signed request, including x-amz- headers, hard-coding the file type on the server, converting the image to a base64 string using a native module, but the problem persists.

On the client-side, calls are made to the server:

uploadToServer() {

    // alert('coming soon!');

    //Go back to profile page
    this.props.navigation.goBack();

    //grab user from navigator params
    let user = this.props.navigation.state.params.user
    let pic = this.state.selected;

    // turn uri into base64
    NativeModules.ReadImageData.readImage(pic.uri, (image) => {
      console.log(image);

      var data = new FormData();
      data.append('picture', {
        uri: image,
        name: pic.filename,
        type: 'image/jpeg'
      });

      //get the signed Url for uploading
      axios.post(api.getPhotoUrl, {fileName: `${pic.filename}`}).then((res) => {

        console.log("get Photo URL response", res);

        //update the user with the new url
        axios.patch(api.fetchUserByID(user.id), {profileUrl: res.data.url}).then((resp) => {

          console.log("Update User response", resp.data);
        }).catch(err => errorHandler(err));

        //upload the photo using the signed request url given to me.
        //DO I NEED TO TURN DATA INTO A BLOB?
        fetch(res.data.signedRequest, {
          method: 'PUT',
          body: data
        }).then((response) => {
          console.log("UPLOAD PHOTO RESPONSE: ", response);
        }).catch(err => errorHandler(err))
      }).catch((err) => errorHandler(err))
    })
  }

The logic for obtaining the signed URL unfolds as follows:

router.post('/users/sign-s3', (req, res) => {
      const s3 = new aws.S3({signatureVersion: 'v4', region: 'us-east-2'});
      const fileName = `${req.user.id}-${req.body.fileName}`;
      const fileType = req.body.fileType;
      const s3Params = {
        Bucket: AWS_S3_BUCKET,
        Key: `images/${fileName}`,
        Expires: 60,
        ContentType: 'image/jpeg',
        ACL: 'public-read'
      };

      s3.getSignedUrl('putObject', s3Params, (err, data) => {
        if (err) {
          console.log(err);
          return res.end();
        }
        const returnData = {
          signedRequest: data,
          url: `https://${AWS_S3_BUCKET}.s3.amazonaws.com/${s3Params.Key}`
        };
        res.write(JSON.stringify(returnData));
        res.end();
        return null;
      });
    });

Answer №1

If you wish for your content to be displayed in the browser, it is essential to convert its type from image to a supported XML format.

For guidance on how to do this, please visit this link and adjust the content type as required.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating an event listener for 'storage' in jQuery using JavaScript

Can anyone tell me how to achieve the same functionality as javascript addEventListener in JQuery? I have been attempting to use it with .bind(), but it seems not to recognize the "storage" keyword. When I tried using 'e' within this context, it ...

How can you use Vue.js @mouseover to target a specific <path> element within an <svg>?

Check out this Codepen example. I am working with an SVG map that contains various paths holding data. My goal is to retrieve the state name when hovering over a specific path. Currently, I have added an event listener to the svg element and am trying to ...

Tips on integrating googleapis with apps script

My goal: I am trying to implement the Google Calendar's API acl.list() in a Google Script using the UrlFetchApp.fetch() function. Issue: The Google script itself has an OAuth token when it runs. However, the problem arises when the UrlFetchApp.fetc ...

Steps for disabling script debugger within Visual Studio 2013

How do I disable script debugging in Visual Studio 2013? I have already disabled script JIT debugging under Tools>Options>Debugging>JIT, and have turned off script debugging in Internet Explorer as well. Despite setting the error option to 'b ...

GAS: What strategies can I implement to optimize the speed of this script?

I have a sheet with multiple rows connected by "";" and I want to expand the strings while preserving the table IDs. ID Column X: Joined Rows 01 a;bcdfh;345;xyw... 02 aqwx;tyuio;345;xyw... 03 wxcv;gth;2364;x89... function expand_j ...

I encountered a ReferenceError stating that the variable "html" is not defined

Recently, I delved into the world of Node.js for the first time. During my attempt to connect my index.html file, an error message stating 'ReferenceError: html is not defined' popped up. Below is the code snippet from my index.js: var http = re ...

Issue: Failed to bundle - Unable to resolve module 'react-native-firebase'

Encountering an issue with Firebase Authentication while running react-native run-android. The error occurs in the node terminal during the execution of \react-native\scripts\..\local-cli\cli.js script. Following the documentation ...

Angular rest call is returning an undefined response object attribute

When attempting to retrieve the attribute of a response object, it is returning as "undefined". var app = angular.module('angularjs-starter', []); app.controller('MainCtrl', function($scope, $http) { $scope.addNewChoice = functio ...

What is the best method of transferring all procedures from frida javascript rpc.exports to python?

I have a JavaScript file containing rpc.exports rpc.exports = { callfunctionsecret: callSecretFun, callfunctionsomethingelse: callSomethingElse, } I am trying to retrieve a list of all these functions in Python, but I have been unable to find a so ...

A 403 error is thrown by the Microsoft Graph API when attempting to delete the authentication method known as "Microsoft Authenticator"

I'm trying to remove a user's Microsoft Authenticator Authentication Method (#microsoft.graph.microsoftAuthenticatorAuthenticationMethod) from their list of authentication methods, but I keep getting a 403 Forbidden error. Below is the code snip ...

Using factories in controllers does not function properly in Angular 1.6

My head is spinning with this one. There are 3 files in play: app.js, app.services.provider.js, admin.js In app.js, I set up my module: (function() { angular.module('myApp', ['ngRoute']).config(function ($routeProvider) { ...

Guide on configuring and executing AngularJS Protractor tests using Jenkins

I am encountering an error with the following configuration: ERROR registration capabilities Capabilities [{platform=WINDOWS, ensureCleanSession=true, browserName=internet explorer, version=}] does not match the current platform LINUX 18:17:05.892 INFO ...

Looking to dynamically set a background image using data fetched from an API in a ReactJS project

Looking to incorporate a background image from an API response in ReactJS Here is some sample code: useEffect(() => { axios.get(`https://apiaddress=${API_KEY}`) .then(res=>{ console.log(res); setRetrieved(res.data); console.log(retrieved ...

React not displaying images with relative paths

In the past, I used to import images in React like this: import person from '../images/image1.png' And then use them in my code like this: <img src={person} alt="" /> Now, for some reason, I want to directly specify the image pa ...

Establishing a default selection for a react dropdown menu filled with data retrieved from an API request

class Select extends React.PureComponent { constructor(props) { super(props) this.state = { value: this.props.initialValue } this.handleChange = this.handleChange.bind(this) } handleChange(e) { e.persist() ...

Error: The variable "$this" has not been defined in the AJAX function

Recently, I've been delving into the world of javascript and ajax. I'm trying to create a dynamic select option list similar to this: https://i.sstatic.net/qELIf.png However, when attempting to compile using Google Chrome Developer tools (F12), ...

Programmatically link validation rules to form fields

I have implemented validation in a form using VeeValidate with Vue.js. Each input displays an error message related to the specific field where the error occurred. <div class="input-group"> <input type="date" class= ...

The button component in my React application is not functioning as expected, despite utilizing the useState and useEffect hooks

I'm having trouble with my Button not working, even though I am using useState and useEffect Check out the code below: import React, { useState, useEffect } from "react"; // import Timeout from "await-timeout"; import ...

Adjusting the size of <nav> element to accommodate its child elements

I've exhausted all possible CSS solutions today in an attempt to make my parent nav tag home-main-nav-menu resize based on its children and grandchildren, but it just won't cooperate. If anyone could provide a clear explanation on how to solve th ...

Is it possible to relocate the file export button to the row of pagination buttons within Datatables implemented with Bootstrap 5?

Utilizing Datatables within a Bootstrap 5 theme has been seamless, with pagination and file export features working effectively. However, the file export button does not align with the theme, prompting me to seek a way to discreetly place it in the same ro ...