Introdution
- This article I will write about how to upload files to Amazon S3.
- S3 is AWS file storage service. Before using the service we need to create the Bucket (which will contain the files we upload).
- FYI: When creating AWS account, some services will be free for 12 months: EC2, S3, RDS, CloudFront (remember to read carefully how free S3 wallet will be 5GB, 20k GET request and 2k PUT request – that’s all, than charging should be careful). However, some other services are always free (even after 12 months – should be spoiled): DynamoDB, Lamda ..
Before start
- Before starting, we need to have an AWS account (if you do not have one, create one).
- Create a new (if you do not have) an AWS Access Key .
Create Bucket
- After having an account and Access Key we need to create a Bucket to test upload files.
- There are several ways to create a Bucket:
- You can create directly on the AWS page
- Or you can create with AWS cli with the command:
aws s3 mb s3://created-by-cli
herecreated-by-cli
is the name of the Bucket you want to set. (mb
turn off make bucket). - Created with the API
- When creating Bucket, there are still many settings (try and see ) such as region, public, CORS .. I and ways 1 and 2 (created on AWS page, aws cli) should only perform tests to know. The rest should be created with API so the settings will be saved without having to remember.
- Before we begin we set up the project a bit.
- Create folders, create projects, initialize git with commands12345mkdir nodejs-aws-s3cd nodejs-aws-s3npm init -ygit init
- Create
config.json
file with the content:1234567<span class="token punctuation">{</span><span class="token property">"BUCKET"</span> <span class="token operator">:</span> <span class="token string">"created-by-api"</span> <span class="token punctuation">,</span><span class="token property">"REGION"</span> <span class="token operator">:</span> <span class="token string">"ap-southeast-1"</span> <span class="token punctuation">,</span><span class="token property">"AWS_ACCESS_KEY"</span> <span class="token operator">:</span> <span class="token string">"NHAP_ACCESS_KEY_CUA_BAN_VAO_DAY"</span> <span class="token punctuation">,</span><span class="token property">"AWS_SECRET_KEY"</span> <span class="token operator">:</span> <span class="token string">"NHAP_SECRET_CUA_BAN_VAO_DAY"</span><span class="token punctuation">}</span> - Create a
makeBucket.js
file (to coincide with the creation of the bucket command in aws-cli)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051<span class="token keyword">const</span> <span class="token constant">AWS</span> <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"aws-sdk"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"./config.json"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">REGION</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">REGION</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">ACCESS_KEY</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">AWS_ACCESS_KEY</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">SECRET_KEY</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">AWS_SECRET_KEY</span> <span class="token punctuation">;</span><span class="token constant">AWS</span> <span class="token punctuation">.</span> config <span class="token punctuation">.</span> <span class="token function">update</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span>accessKeyId <span class="token punctuation">:</span> <span class="token constant">ACCESS_KEY</span> <span class="token punctuation">,</span>secretAccessKey <span class="token punctuation">:</span> <span class="token constant">SECRET_KEY</span> <span class="token punctuation">,</span>region <span class="token punctuation">:</span> <span class="token constant">REGION</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">var</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AWS <span class="token punctuation">.</span> S3</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> params <span class="token operator">=</span> <span class="token punctuation">{</span>Bucket <span class="token punctuation">:</span> config <span class="token punctuation">.</span> <span class="token constant">BUCKET</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token function-variable function">editBucketCORS</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span>s3 <span class="token punctuation">.</span> <span class="token function">putBucketCors</span> <span class="token punctuation">(</span><span class="token punctuation">{</span>Bucket <span class="token punctuation">:</span> config <span class="token punctuation">.</span> <span class="token constant">BUCKET</span> <span class="token punctuation">,</span>CORSConfiguration <span class="token punctuation">:</span> <span class="token punctuation">{</span>CORSRules <span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>AllowedHeaders <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"*"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span>AllowedMethods <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"PUT"</span> <span class="token punctuation">,</span> <span class="token string">"POST"</span> <span class="token punctuation">,</span> <span class="token string">"DELETE"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span>AllowedOrigins <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"*"</span> <span class="token punctuation">]</span><span class="token punctuation">}</span> <span class="token punctuation">,</span><span class="token punctuation">{</span>AllowedMethods <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"GET"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span>AllowedOrigins <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"*"</span> <span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">,</span>err <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> err <span class="token punctuation">,</span> err <span class="token punctuation">.</span> stack <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">else</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`Edit Bucket CORS succeed!`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>s3 <span class="token punctuation">.</span> <span class="token function">createBucket</span> <span class="token punctuation">(</span> params <span class="token punctuation">,</span> <span class="token punctuation">(</span> err <span class="token punctuation">,</span> data <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> err <span class="token punctuation">,</span> err <span class="token punctuation">.</span> stack <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">else</span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token function">editBucketCORS</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> - The current directory structure is ntn:12345678.├── config.json├── makeBucket.js├── node_modules├── package.json└── package-lock.json
- The
makeBucket.js
file will take configuration inconfig.json
and create a new Bucket with the namecreated-by-api
. Then adjust the bucketCORS
settings with theeditBucketCORS
function. I tried setting up at the time of creating the bucket but it didn’t work. Search doc, there is only 1 edit phase after creating the bucket here . - Install the dependency package
npm i aws-sdk
, configure the key correctly, we run the file with:node makeBucket.js
will have the following output as successfully created:1234node makeBucket.js{ Location: 'http://created-by-api.s3.amazonaws.com/' }Edit Bucket CORS succeed! - We can also check by web interface or cli, cli will have output like this:12345$ aws s3 ls2020-02-18 23:05:59 craft-created2020-02-22 22:28:01 created-by-api2020-02-22 10:49:55 created-by-cli
- Only run 1
makeBucket.js
file, why configure the project, config things to do? Be familiar with how to manage the configuration files related to the Key of services like AWS or Google … one way is that you save to the config file and add that file to .gitignore. (If deployed on the cloud, these configuration files should be saved in encrypted areas and limited access so it is safer.) Then you can safely push your project to github or share the repo link to others. - File .gitignore ntn:123config.jsonnode_modules/
Upload the file
Bucket
we have test file upload to S3- Depending on our service, we have different ways to upload files to S3.
Direct upload
- First lesson: let’s say your server creates its own
invoice - hóa đơn
then we need to push the file directly to S3 and return the link to the customer to see the invoice. - Let the server directly push the file to S3. We create the file
directUpload.js
with the following content:123456789101112131415161718192021222324252627282930313233<span class="token keyword">const</span> <span class="token constant">AWS</span> <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"aws-sdk"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"fs"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"./config.json"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">BUCKET</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">BUCKET</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">REGION</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">REGION</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">ACCESS_KEY</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">AWS_ACCESS_KEY</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">SECRET_KEY</span> <span class="token operator">=</span> config <span class="token punctuation">.</span> <span class="token constant">AWS_SECRET_KEY</span> <span class="token punctuation">;</span><span class="token keyword">const</span> localImage <span class="token operator">=</span> <span class="token string">"./cat.jpeg"</span> <span class="token punctuation">;</span><span class="token keyword">const</span> imageRemoteName <span class="token operator">=</span> <span class="token template-string"><span class="token string">`directUpload_catImage_</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">new</span> <span class="token class-name">Date</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">getTime</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">.jpeg`</span></span> <span class="token punctuation">;</span><span class="token constant">AWS</span> <span class="token punctuation">.</span> config <span class="token punctuation">.</span> <span class="token function">update</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span>accessKeyId <span class="token punctuation">:</span> <span class="token constant">ACCESS_KEY</span> <span class="token punctuation">,</span>secretAccessKey <span class="token punctuation">:</span> <span class="token constant">SECRET_KEY</span> <span class="token punctuation">,</span>region <span class="token punctuation">:</span> <span class="token constant">REGION</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">var</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AWS <span class="token punctuation">.</span> S3</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>s3 <span class="token punctuation">.</span> <span class="token function">putObject</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span>Bucket <span class="token punctuation">:</span> <span class="token constant">BUCKET</span> <span class="token punctuation">,</span>Body <span class="token punctuation">:</span> fs <span class="token punctuation">.</span> <span class="token function">readFileSync</span> <span class="token punctuation">(</span> localImage <span class="token punctuation">)</span> <span class="token punctuation">,</span>Key <span class="token punctuation">:</span> imageRemoteName<span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function">promise</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> res <span class="token operator">=></span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`Upload succeeded - `</span></span> <span class="token punctuation">,</span> res <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span> err <span class="token operator">=></span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Upload failed:"</span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> - The directory now adds 2 files:
directUpload.js
andcat.jpg
1234567891011.├── cat.jpg├── config.json├── directUpload.js├── makeBucket.js├── node_modules├── package.json└── package-lock.json1 directory, 6 files - Test run the program, delicious upload ok:123node directUpload.jsUpload succeeded - { ETag: '"550cf35812c2447027f8e4d547a78adb"' }
Upload with signedURL
- Problem 2: Your application allows users to upload files directly to S3. At this time, it is not possible for users to upload to the server and then the server to upload to S3 again. Instead, the Client will call the server to get a
signedURL
and the client uses it to upload files to S3. - First on the server side we create a file:
uploadWithSignedURL.js
with the following content:12345678910111213141516171819202122232425262728293031323334353637<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"cors"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> aws <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"aws-sdk"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"express"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> configAWS <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"./config"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>app <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token function">cors</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>app <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">"/sign-s3"</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> req <span class="token punctuation">,</span> res <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">const</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">aws <span class="token punctuation">.</span> S3</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> fileName <span class="token operator">=</span> req <span class="token punctuation">.</span> query <span class="token punctuation">[</span> <span class="token string">"file-name"</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">const</span> fileType <span class="token operator">=</span> req <span class="token punctuation">.</span> query <span class="token punctuation">[</span> <span class="token string">"file-type"</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">const</span> s3Params <span class="token operator">=</span> <span class="token punctuation">{</span>Bucket <span class="token punctuation">:</span> configAWS <span class="token punctuation">.</span> <span class="token constant">BUCKET</span> <span class="token punctuation">,</span>Key <span class="token punctuation">:</span> fileName <span class="token punctuation">,</span>Expires <span class="token punctuation">:</span> <span class="token number">60</span> <span class="token punctuation">,</span>ContentType <span class="token punctuation">:</span> fileType <span class="token punctuation">,</span><span class="token constant">ACL</span> <span class="token punctuation">:</span> <span class="token string">"public-read"</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>s3 <span class="token punctuation">.</span> <span class="token function">getSignedUrl</span> <span class="token punctuation">(</span> <span class="token string">"putObject"</span> <span class="token punctuation">,</span> s3Params <span class="token punctuation">,</span> <span class="token punctuation">(</span> err <span class="token punctuation">,</span> data <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`getSignedUrl error: `</span></span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">const</span> returnData <span class="token operator">=</span> <span class="token punctuation">{</span>signedRequest <span class="token punctuation">:</span> data <span class="token punctuation">,</span>url <span class="token punctuation">:</span> <span class="token template-string"><span class="token string">`https://</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> configAWS <span class="token punctuation">.</span> <span class="token constant">BUCKET</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">.s3.amazonaws.com/</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> fileName <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span><span class="token punctuation">}</span> <span class="token punctuation">;</span>res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> returnData <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>app <span class="token punctuation">.</span> <span class="token function">listen</span> <span class="token punctuation">(</span> <span class="token number">3000</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"come here babe..."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> - What does the server segment do? Initialize an api that receives a request with route
sign-s3
and queries: file-name, file-type. Then request signedURL (withs3.getSignedUrl
) and return it to the client. That’s enough, the rest is for the client. - Here I will create an
ugly-client
index.html
file with the following content:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253<span class="token tag"><span class="token tag"><span class="token punctuation"><</span> html</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span> head</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> head</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span> body</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name">type</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> file <span class="token punctuation">"</span></span> <span class="token attr-name">id</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> file-input <span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span> p</span> <span class="token attr-name">id</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> status <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Please select a file <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> p</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span> script</span> <span class="token punctuation">></span></span> <span class="token script language-javascript"><span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">"file-input"</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function-variable function">onchange</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">const</span> files <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">"file-input"</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> files <span class="token punctuation">;</span><span class="token keyword">const</span> file <span class="token operator">=</span> files <span class="token punctuation">[</span> <span class="token number">0</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span> file <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token function">alert</span> <span class="token punctuation">(</span> <span class="token string">"No file selected."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token function">getSignedRequest</span> <span class="token punctuation">(</span> file <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token function-variable function">getSignedRequest</span> <span class="token operator">=</span> file <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">const</span> xhr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function">open</span> <span class="token punctuation">(</span><span class="token string">"GET"</span> <span class="token punctuation">,</span><span class="token template-string"><span class="token string">`http://localhost:3000/sign-s3?file-name=</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> file <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">&file-type=</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> file <span class="token punctuation">.</span> type <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function-variable function">onreadystatechange</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> xhr <span class="token punctuation">.</span> readyState <span class="token operator">===</span> <span class="token number">4</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> xhr <span class="token punctuation">.</span> status <span class="token operator">===</span> <span class="token number">200</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">parse</span> <span class="token punctuation">(</span> xhr <span class="token punctuation">.</span> responseText <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token function">uploadFile</span> <span class="token punctuation">(</span> file <span class="token punctuation">,</span> response <span class="token punctuation">.</span> signedRequest <span class="token punctuation">,</span> response <span class="token punctuation">.</span> url <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><span class="token function">alert</span> <span class="token punctuation">(</span> <span class="token string">"Could not get signed URL."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token function-variable function">uploadFile</span> <span class="token operator">=</span> <span class="token punctuation">(</span> file <span class="token punctuation">,</span> signedRequest <span class="token punctuation">,</span> url <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">const</span> xhr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function">open</span> <span class="token punctuation">(</span> <span class="token string">"PUT"</span> <span class="token punctuation">,</span> signedRequest <span class="token punctuation">)</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function-variable function">onreadystatechange</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> xhr <span class="token punctuation">.</span> readyState <span class="token operator">===</span> <span class="token number">4</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> xhr <span class="token punctuation">.</span> status <span class="token operator">===</span> <span class="token number">200</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`Upload succeed to: </span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> url <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><span class="token function">alert</span> <span class="token punctuation">(</span> <span class="token string">"Could not upload file."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>xhr <span class="token punctuation">.</span> <span class="token function">send</span> <span class="token punctuation">(</span> file <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> script</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span> body</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span> html</span> <span class="token punctuation">></span></span> - Here, the folder has 2 new files:12345678910111213.├── cat.jpg├── config.json├── directUpload.js├── index.html├── makeBucket.js├── node_modules├── package.json├── package-lock.json└── uploadWithSignedURL.js1 directory, 8 files
- Talk a little bit. The file only has 1 input tag for the user to select the file.
Script
will listenonchange
to send the request to the server usinggetSignedRequest
. Here I am fixing the local URL hard as you see:http://localhost:3000/sign-s3?file-name=${file.name}&file-type=${file.type}
. After receiving the signedURL returned by the server, the client will upload the file to S3 using:uploadFile
. - Ok, got it Test it out. First
npm i express cors
. Run the server first:1234node uploadWithSignedURL.jscome here babe... - Then open
index.html
file with chrome and selectcat.jpg
file wait a while check on theconsole
window of the browser to see the form as if the upload was successful (if failed any step will turn on popup):12Upload succeed to: https://created-by-api.s3.amazonaws.com/cat.jpg - Sure you can check back on the AWS site, or faster with aws-cli:1234$ aws s3 ls s3://created-by-api2020-02-24 23:24:19 58836 cat.jpg2020-02-24 23:21:51 58836 directUpload_lovelyCat_1582561310482.jpg
- As you can see there are 2 files 1 file
directUpload
from server nodejs and 1 file uploaded from client side with signedURL. - Thank you for watching here! The full code in this article is here, so read through ReadMe.md if you can run it!
- Happy using AWS service!