Save Changes to a Note

Is there a way to use Storage.vault.remove() to delete the old attachments? And… how would I find the key for the attachment? file.filename?

It should be similar to the way we get an object here https://github.com/AnomalyInnovations/serverless-stack-demo-client/blob/master/src/containers/Notes.js#L31.

attachmentURL = await Storage.vault.get(attachment);

I was getting the following error when trying to upload a new file:

ETagMissing: No access to ETag property on response. Check CORS configuration to expose ETag header.

I believe My CORS config was correct, see below. I added the Etag to my cors config and that fixed the issue but shouldn’t this be covered by the AllowedHeader line?

<ExposeHeader>ETag</ExposeHeader>

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

That is weird. I haven’t seen this error before. What did your final CORS config end up looking like?

My ‘saving’ and ‘deleting’ of notes is stuck in loading mode and never actually is accomplished. I logged on to Cloud Watch to try and see what was going on and my execution log looked ok from what I could tell but I am getting the following alarm:

Yeah this basically means that Dynamo is trying to auto-scale because it is going over capacity. You can check in the CloudWatch logs if your requests are timing out.

I’m getting the “KeyTooLongError” when I try to delete the previous attachment. The 400 error that is returned shows two extra characters “25” towards the end of the key for some reason.

My awsLin.js

export async function s3Delete(fileKey) {
    console.log("fileKey: " +fileKey);
    const removed = await Storage.vault.remove(fileKey);
    console.log(removed);
    return removed;
}

My Notes.js

  handleSubmit = async event => {
    event.preventDefault();
    let attachment;
    if (this.file && this.file.size > config.MAX_ATTACHMENT_SIZE) {
      alert(`Please pick a file smaller than ${config.MAX_ATTACHMENT_SIZE/1000000} MB.`);
      return;
    }
    this.setState({ isLoading: true });
    try {
      if (this.file) {
        if (this.state.attachmentURL) {
          await s3Delete(this.state.attachmentURL);
        }
        attachment = await s3Upload(this.file);
      }
      await this.saveNote({
        content: this.state.content,
        attachment: attachment || this.state.note.attachment
      });
      this.props.history.push("/");
    } catch (e) {
      alert(e);
      this.setState({ isLoading: false });
    }
  }

What is the fileKey in your case? Is it the full URL of the S3 file?

It is the response from Storage.vault.get() and does appear to be an URL for the S3 file.

  async componentDidMount() {
    try {
      let attachmentURL;
      const note = await this.getNote();
      const { content, attachment } = note;

      if (attachment) {
        attachmentURL = await Storage.vault.get(attachment);
      }

      this.setState({
        note,
        content,
        attachmentURL,
      });
    } catch (e) {
      alert(e);
    }
  }

  getNote() {
    return API.get("notes", `/notes/${this.props.match.params.id}`);
  }

I don’t remember exactly but I don’t think the key is supposed to be the full URL it might just be the file name?

For anyone trying to find out what the ‘filekey’ is for deleting a file.
The Storage’s remove() function takes in a key to remove the file.
The key is the file name.
In your Notes.js, this will be: this.state.note.attachment

We set this in the s3Upload function in our awsLib.js file. We took the file in as a parameter, and we formatted a filename to pass into the Storage.vault.put() method as {CurrentTimesStamp}-{file.name}

const filename =${Date.now()}-${file.name} <- this is what we used to create the file. Would make sense we also use this to remove the file.

If you want to be sure, you can console.log(note) in your componentDidMount() right after fetching the note with this.getNote(), and look at what is listed in the ‘attachment’ field

1 Like

Thanks for the added details!

1 Like

So I am having a problem with saving an updated note, once I add new text and hit save, it takes me back to the home page as it should but errors out. The error message states that it cannot read property ‘trim’ of null, and the reason that is happening is because it is somehow saving it in dynamoDb with the content key set to null: true instead of just updating the content with the new text I added. And so when it goes back to the home page and does the GET request, it is pulling the note that has content key with null: true. And when I create a new note, everything works fine. I’m thinking it has something to do with the update API function, specifically where it sets the expression attribute values:
ExpressionAttributeValues: {
“:attachment”: data.attachment || null,
“:content”: data.content || null
}
But I am not completely sure, I also thought maybe I had a typo somewhere in Notes.js file but I went ahead and just copied and pasted that file from the Github repo client demo and it still does the same thing. Any help is much appreciated!

Could it be that in your React code you are not passing in the content?