Closed gpavlov2016 closed 5 months ago
Hi 👋 Thanks for opening up the issue. The feature to support the backend is not yet released since we are actively working on it. There is a tagged release gen2-storage
which should help access this new backend.
npm install aws-amplify@gen2-storage
import {downloadData} from 'aws-amplify/storage'
const image = downloadData({path: 'thumbnails/6d946476-4c41-4124-92b1-1f05b26c7080.jpg'});
More on this will come out with docs
I am seeing something with getUrl. I am trying to do a test where I upload a file , generate a link on a page, then download the file. The upload is working but the link that I am getting back using getUrl keeps giving me an access denied 403 error.
it successfully works for public access but not private.
I have added 'private/{entity_id}/*': [allow.entity('identity').to(['read', 'write', 'delete'])] to the access of my defineStorage
uploads work fine but downloads don't
@gpavlov2016 and @strickon, you should now be able to verify/test this on v6.2.0
of Amplify. Can you upgrade to the latest version and let us know if you still experience this issue?
@strickon can you provide us with a code sample. The permission you have should let you read & write into private/CURRENT_USER_ID/*
I have figured out what I think is causing the problem but not sure how to address is. So I am using the amplify ui storage manger component to upload the file. It is going into a private folder in the bucket. I am then using getUrl to generate a presigned url using the server context. The problem I believe is that the url being generated doesn't match the s3 bucket url for the identity id portion. I am a logged in user uploading to a private folder.
I see the files in the bucket with a path.
Now I generate a url with getUrl using the server context and the path in the url is different from the path in the bucket. the identityId portion of the url is different.
I don't know which part is incorrect. Is the StorageManager putting the file in the wrong private folder with the wrong identity id or is the getUrl generating the wrong download url?
Everything works fine if I upload and download using public access level which puts it into the public folder.
here is the upload component from amplify-ui . it requires "use client"; (could this be an issue?)
export default function Upload() { return ( <StorageManager accessLevel='private' acceptedFileTypes={['.doc','.pdf','.docx']} autoUpload={false} maxFileCount={1} path={"upload/"} processFile={processFile} onUploadSuccess={({ key }) => { //Store files console.log('Upload Success '+key) CreateUpload(key) }}
); }
Download getUrl
Here is the function to create teh download url
const CreateDownload = async (key: string, access: string) => {
return (await runWithAmplifyServerContext({
nextServerContext: null,
operation: async (contextSpec) =>
(await getUrl(contextSpec, {
key: key,
options: {
accessLevel: access, // can be 'private', 'protected', or 'guest' but defaults to guest
},
})).url.toString()}))
}
Let me know any thoughts.
I updated my app and it wasn't working but found the source of the issue and it works now. The documentation was a bit sparse.
The problem was that the the server context was null in the geturl example so it only worked for public files. the cookies needed to be passed in to generate the proper url for private access.
nextServerContext: { cookies },
Could you point out where u had difficulty with docs? We can update it to give clarity.
https://docs.amplify.aws/gen2/build-a-backend/server-side-rendering/#pageMain
The particular example with getUrl was a bit confusing with regards to the server context. It would be good to have some more detailed examples of the storage component and browser based uploads and downloads.
Thanks appreciate the feedback. It is in works and should start seeing more indepth docs soon :)
@gpavlov2016 and @strickon, you should now be able to verify/test this on
v6.2.0
of Amplify. Can you upgrade to the latest version and let us know if you still experience this issue?
@cwomack Upgrading to v6.2 solved the issue, thank you!
I did have to use the field name path
in the argument object to getUrl
while the value is called key
in S3 console so its a bit confusing because there is another field called key
in the param description.
In summary, it worked as follows:
getUrl({ path: 'thumbnails/4081c322-0086-4035-9181-02c124e99350.jpg' })
@gpavlov2016 Thanks for the feedback and we will work on it. We have updated our docs site to reflect the new usage.
key
usage is going to be deprecated in future version and all API using key should have a warning for it.
https://docs.amplify.aws/react/build-a-backend/storage/set-up-storage/
Hopefully this helps clarify the storage API usage. Let us know if there is anything else we can help with or we can close the issue.
Hi guys, apologies for bringing this one up again but I think this is the best place.
I'm new to AWS and am learning Amplify, and following this: https://docs.amplify.aws/react/build-a-backend/storage/set-up-storage/#upload-your-first-file.
At that step, when I try to actually upload a file, I get a 403 AccessDenied
Amplify error when trying to use the uploadData
function.
I think I have set everything right.
//backend.ts:
defineBackend({
auth,
data,
sayHello,
storage
});
// storage/resource.ts:
export const storage = defineStorage({
name: "photosStorage",
access: (allow) => ({
"experiences/{entity_id}/*": [
allow.entity("identity").to(["read", "write", "delete"]),
allow.guest.to(["read"]),
],
}),
});
<button
onClick={() =>
uploadData({
path: `experiences/${file.name}`,
data: file,
})
}
>
Upload
</button>
Anyone else in my situation / AccessDenied error when following the tutorial? Not sure where I went wrong.
Hi @danCoda 👋
It looks like your access rules only allows guest (unauthenticated) users to read from the bucket but you are trying to write to the bucket.
To write to the bucket, your access rules allow authenticated users with an entity id. You have to pass the user's entity id into the file path like so:
import { uploadData } from 'aws-amplify/storage';
try {
const result = await uploadData({
path: ({identityId}) => `experiences/${identityId}/${file.name}.jpg`
data: file,
}).result;
console.log('Succeeded: ', result);
} catch (error) {
console.log('Error : ', error);
}
Appreciate your assistance @chrisbonifacio !
(Tip for anyone - I feel that the AWS sandbox needs to be restarted every now and again)
I got it working with your suggestion. I was also referencing this Amplify Storage tutorial and I there is some misunderstanding. Why did I have to remove the bucket
option below to get it working (along with your suggestion)?
async function tryDownload() {
try {
const result = await downloadData({
path: ({ identityId }) => `profile-pictures/${identityId}/image.jpg`, // User's entity id has been passed.
options: {
// bucket: "amplifyTeamDrive", // NOTE: No good, I had to remove this to work.
},
}).result;
console.log("Result", result);
} catch (error) {
console.log(`Error: ${error}`);
}
}
// My storage configuration:
export const storage = defineStorage({
name: "amplifyTeamDrive", // NOTE: This is the bucket name?
access: (allow) => ({
"profile-pictures/{entity_id}/*": [
allow.entity("identity").to(["read", "write", "delete"]),
],
}),
});
Before opening, please confirm:
JavaScript Framework
Next.js
Amplify APIs
Storage
Amplify Version
v6
Amplify Categories
storage
Backend
Amplify Gen 2 (Preview)
Environment information
Describe the bug
storage\resource.ts:
downloadData from another file:
Response from server:
Request headers:
Expected behavior
Expected to get the file
Reproduction steps
Define the storage resources mentioned above and run downloadData for any object key under the authorized key prefix for allow.guest.to(['read'])
Code Snippet
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response