AWS S3 - Image cannot be displayed because it contains errors

3k Views Asked by At

I am currently building a signup form with React, Redux, JavaScript, Node, Adonisjs. I'm attempting to upload profile images to my AWS s3 Bucket. At the moment I've got it so the file is appearing in the bucket. However when I try to click on the link provided by AWS s3 i get the following error. AWS ERROR IMAGE.

I have set my permissions to public and I have provided the correct credential keys. I'm stuck on how to solve this so any help would be greatly appreciated. Please see code below.

Below is my AWS Controller:

"use strict";

require("dotenv").config();
const aws = require("aws-sdk");
const fs = require("fs");
const Helpers = use("Helpers");
const Drive = use("Drive");

class awsController {
  async upload({ request, response }) {
    aws.config.update({
      region: "ap-southeast-2", // AWS region
      accessKeyId: process.env.S3_KEY,
      secretAccessKey: process.env.S3_SECERT
    });

    const S3_BUCKET = process.env.S3_BUCKET;

    const s3Bucket = new aws.S3({
      region: "ap-southeast-2",
      accessKeyId: process.env.S3_KEY,
      secretAccessKey: process.env.S3_SECERT,
      Bucket: process.env.S3_BUCKET
    }); // Create a new instance of S3

    const fileName = request.all().body.fileName;
    console.log(fileName);
    const fileType = request.all().body.fileType;

    const params = {
      Bucket: S3_BUCKET,
      Key: fileName,
      ContentType: fileType,
      ACL: "public-read"
    };

    s3Bucket.putObject(params, function(err, data) {
      if (err) {
        response.send(err);
      }
      console.log(data);

      const returnData = {
        signedRequest: data,
        url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
      };

      console.log(returnData);
      response.send("Success");
    });
  }
}

module.exports = awsController;

** Below handles uploading of file **


import React, { Component } from "react";
import axiosAPI from "./../resorterAPI";
import axios from "axios";

class ImageUpload extends Component {
  constructor(props) {
    super(props);
    this.state = {
      success: false,
      url: ""
    };
  }

  handleChange = event => {};

  handleUpload = event => {
    let uploadedFile = this.uploadInput.files[0];

    // Splits name of file
    let fileParts = this.uploadInput.files[0].name.split(".");
    let fileName = fileParts[0];
    let fileType = fileParts[1];
    let fullFileName = uploadedFile.name;

    console.log("preparing upload");

    axiosAPI
      .post("/s3Upload", {
        body: {
          fileName:
            Math.round(Math.random() * 1000 * 300000).toString() +
            "_" +
            uploadedFile.name,
          fileType: fileType
        }
      })
      .then(response => {
        console.log("Success");
      });
  };

  render() {
    return (
      <div>
        <center>
          <input
            onChange={this.handleChange}
            ref={ref => {
              this.uploadInput = ref;
            }}
            type="file"
          />
          <br />
          <button onClick={this.handleUpload}> Upload </button>
        </center>
      </div>
    );
  }
}

export default ImageUpload;

**Below is where the image upload service is called **

import React from "react";

// Redux
import { Field, reduxForm } from "redux-form";
import { connect } from "react-redux";
import { getCountry } from "./../../redux/actions/getCountryAction.js";
import Store from "./../../redux/store.js";

// Services
import axiosAPI from "./../../api/resorterAPI";
import ImageUpload from "./../../api/services/ImageUpload";

// Calls a js file with all area codes matched to countries.
import phoneCodes from "./../../materials/PhoneCodes.json";

// Component Input
import {
  renderField,
  renderSelectField,
  renderFileUploadField
} from "./../FormField/FormField.js";

// CSS
import styles from "./signupForm.module.css";
import classNames from "classnames";

function validate(values) {
  let errors = {};

  if (!values.specialisations) {
    errors.firstName = "Required";
  }

  if (!values.resort) {
    errors.lastName = "Required";
  }

  if (!values.yearsOfExperience) {
    errors.email = "Required";
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = "Invalid Email";
  }

  if (!values.spokenLanguages) {
    errors.password = "Required";
  }

  if (values.sport !== values.confirmPassword) {
    errors.confirmPassword = "Passwords don't match";
  }

  return errors;
}

class SignupFormStepTwo extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      countries: [],
      selectedCountry: [],
      dialCodes: []
    };
  }

  // Below gets the countries from axios call made in redux actions
  async componentDidMount() {
    const countries = await getCountry();
    // The below maps through the json file and gets all the dial codes
    const codes = phoneCodes.phoneCode.map(code => {
      return code.dial_code;
    });
    return this.setState({ countries: countries, dialCodes: codes });
  }

  // Handles when someone changes the select fields
  handleChange = event => {
    const selectedCountry = event.target.value;
    return this.setState({ selectedCountry: selectedCountry });
  };

  // uploadFile = (values, url = "") => {
  //   axiosAPI.post("/displayImageUpload", { ...values, imageURL: url}).then(response => {
  //     console.log("Success");
  //   })
  // }

  render() {
    return (
      <div>
        <form onSubmit={this.props.handleSubmit}>
          <div className={styles.signupContainer}>
            <div className={styles.signupInputContainer}>
              {/* <Field
                name="displayImage"
                component={renderFileUploadField}
                type="text"
                label="Display Image"
              /> */}

              <ImageUpload />

              <div
                className={classNames({
                  [styles.bioField]: true,
                  [styles.signupInputContainer]: true
                })}
              >
                <Field
                  name="bio"
                  component={renderField}
                  type="text"
                  label="Bio"
                  placeholder="Introduce yourself - Where you're from, what your hobbies are, etc..."
                />
              </div>
            </div>

            {/* Renders the select field  */}
            <div className={styles.signupInputContainer}>
              <Field
                name="specialisations"
                component={renderSelectField}
                type="select"
                label="Specialisations"
                placeholder="Specialisations"
                options={this.state.countries}
                onChange={this.handleChange}
                multiple={false}
              />

              <Field
                name="resort"
                component={renderSelectField}
                options={this.state.dialCodes}
                type="select"
                label="Resort"
                placeholder="Select the resorts you can work at"
              />

              <Field
                name="yearsOfExperience"
                component={renderSelectField}
                options={this.state.dialCodes}
                type="select"
                label="Years of Experience"
              />

              <Field
                name="spokenLanguages"
                component={renderSelectField}
                options={this.state.dialCodes}
                type="select"
                label="Spoken Languages"
              />
            </div>
          </div>
          <div className={styles.signupButtonContainer}>
            <button className={styles.signupButton} type="submit">
              {" "}
              Submit{" "}
            </button>
          </div>
        </form>
      </div>
    );
  }
}

// destroyOnUnmount - saves it in state
SignupFormStepTwo = reduxForm({
  form: "signupStageTwo",
  destroyOnUnmount: false,
  validate
})(SignupFormStepTwo);

const mapStateToProps = state => {
  return {
    form: state.form
  };
};

export default SignupFormStepTwo;

1

There are 1 best solutions below

1
Max Kelly On

UPDATE: Solved the error thanks to Jarmod, I was actually not separating the file extension from the file name so it was uploading image.png.png.