<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>s3 Archives - Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/tag/s3/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/tag/s3/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Fri, 01 Dec 2023 04:17:59 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>s3 Archives - Tomoshare</title>
	<link>https://blog.tomosia.com.vn/tag/s3/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</title>
		<link>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/</link>
					<comments>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Fri, 01 Dec 2023 04:17:57 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[s3]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2125</guid>

					<description><![CDATA[<p>Việc lưu trữ và quản lý file trên đám mây đã trở thành một phần quan trọng trong&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/">[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Việc lưu trữ và quản lý file trên đám mây đã trở thành một phần quan trọng trong quá trình phát triển ứng dụng. Việc upload nhiều files đồng thời không chỉ giúp tiết kiệm thời gian mà còn tối ưu hiệu suất, đặc biệt quan trọng đối với các ứng dụng yêu cầu xử lý lượng lớn dữ liệu.</p>



<p class="wp-block-paragraph"> Giả sử chúng ta có 1000 files cần upload lên S3 Storage. </p>



<p class="wp-block-paragraph">Thông thường, chúng ta sẽ làm như sau: </p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="foreach ($uploadFiles as $uploadFile) {
    $response = $this-&gt;s3StorageClient-&gt;putObject([
        'Bucket'       =&gt; ****,
        'Key'          =&gt; $uploadFile['filename'],
        'SourceFile'   =&gt; $uploadFile['content'],
        'ACL'          =&gt; 'public-read'
//        ....
   ]);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($uploadFiles </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $uploadFile) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $response </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">putObject</span><span style="color: #F6F6F4">([</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Bucket</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">       </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">****</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Key</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">filename</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">SourceFile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">   </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ACL</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">public-read</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #7B7F8B">//        ....</span></span>
<span class="line"><span style="color: #F6F6F4">   ]);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Theo cách trên, nếu chúng ta upload 10 files thì sẽ mất 10 lần để xử lý putObject, nếu upload 1000 files thì sẽ lần lượt xử lý putObject 1000 lần.</p>



<p class="wp-block-paragraph">Để giải quyết việc này, AWS PHP SDK có cung cấp một class CommandPool, class này có thể thực thi nhiều lệnh AWS cùng lúc.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$commands = [];
foreach ($uploadFiles as $uploadFile) {
    $commands[] = $this-&gt;s3StorageClient-&gt;getCommand('PutObject', [
        'Bucket'       =&gt; ****,
        'Key'          =&gt; $uploadFile['filename'],
        'SourceFile'   =&gt; $uploadFile['content'],
        'ACL'          =&gt; 'public-read'
    ]);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$commands </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> [];</span></span>
<span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($uploadFiles </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $uploadFile) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $commands[] </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getCommand</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">PutObject</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, [</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Bucket</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">       </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">****</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Key</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">filename</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">SourceFile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">   </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ACL</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">public-read</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F6F6F4">    ]);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Đầu tiên, không thực thi lệnh putObject trong vòng lặp mà hãy sử dụng <strong>getCommand</strong> để tạo lệnh cho <strong>putObject</strong> và lưu trữ nó trong một mảng.</p>



<p class="wp-block-paragraph">Sau đó, bạn có thể dễ dàng thực thi các lệnh đồng thời bằng cách đưa s3 instance và mảng commands được vào phương thức <strong>CommandPool::batch.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="CommandPool::batch($this-&gt;s3StorageClient, $commands);" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1; font-style: italic">CommandPool</span><span style="color: #F286C4">::</span><span style="color: #62E884">batch</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient, $commands);</span></span></code></pre></div>



<p class="wp-block-paragraph">Ở đây chúng ta có thể lấy files đồng thời sau khi gọi hàm <strong>CommandPool::batch</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$responses = CommandPool::batch($this-&gt;s3StorageClient, $commands);

foreach ($responses as $response) {
  // code here
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$responses </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">CommandPool</span><span style="color: #F286C4">::</span><span style="color: #62E884">batch</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient, $commands);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($responses </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $response) {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// code here</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Em cũng đã triển khai cách trên áp dụng vào dự án và cũng khá hiệu quả về performance.</p>



<p class="wp-block-paragraph">Đối với những bài toán upload số lượng files lên đến hàng trăm nghìn, hàng triệu, chúng ta có thể zip từng nhóm files rồi thực hiện upload đồng thời theo cách trên, nhưng cần sử dụng thêm một service để giải nén file zip sau khi upload (AWS Lambda chẳng hạn).</p>



<p class="wp-block-paragraph"><br><strong>Tài liệu tham khảo: </strong></p>



<ul class="wp-block-list">
<li><a href="https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_commands.html#command-pool">https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_commands.html#command-pool</a></li>



<li><a href="https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CommandPool.html">https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CommandPool.html</a></li>
</ul>
<p>The post <a href="https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/">[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Sử dụng localstack để giả lập upload file s3</title>
		<link>https://blog.tomosia.com.vn/su-dung-localstack-de-gia-lap-upload-file-s3/</link>
					<comments>https://blog.tomosia.com.vn/su-dung-localstack-de-gia-lap-upload-file-s3/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Sun, 08 Oct 2023 10:04:01 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[localstack]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=847</guid>

					<description><![CDATA[<p>Hí anh em! Tôi&#160;saiury92&#160;đây ! Trong một thập niên qua và cũng có thể một vài thập niên&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/su-dung-localstack-de-gia-lap-upload-file-s3/">Sử dụng localstack để giả lập upload file s3</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Hí anh em! Tôi&nbsp;<a rel="noreferrer noopener" href="https://saiury92.github.io/" target="_blank">saiury92&nbsp;</a>đây ! Trong một thập niên qua và cũng có thể một vài thập niên tới AWS vẫn làm bố của các Cloud Service Providers, 10 dự án thì tới 9 dự án cần upload file lên Amazon S3. Trong bài viết hôm nay, tôi sẽ giúp các đồng dâm thực hiện việc giả lập upload file s3 ở local mà không cần AWS account. Let&#8217;s go !!!!</p>



<h4 id="localstack" class="wp-block-heading"><strong>LocalStack ?</strong></h4>



<p class="wp-block-paragraph">LocalStack là một nền tảng mã nguồn mở cho phép bạn chạy và giả lập các dịch vụ AWS ở local. LocalStack hỗ trợ nhiều dịch vụ AWS khác nhau : S3, Lambda, SNS, ES, SES, API Gateway, &#8230;. Dịch vụ cần quan tâm của chúng ta là S3.</p>



<h4 id="start-localstack-bang-docker" class="wp-block-heading">Start LocalStack bằng docker ?</h4>



<p class="wp-block-paragraph">Chúng ta có thể setup LocalStack trực tiếp trên máy thông qua pip:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="pip install localstack" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">pip install localstack</span></span></code></pre></div>



<p class="wp-block-paragraph">Nhưng bây giờ là thời đại của containerization, chúng ta mà không sử dụng docker là bị sếp nói là lạc hậu đấy ! Để chạy localstack với docker compose cho S3, anh em có thể sử dụng docker-compose.yml file dưới đây:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.9'
services:
  localstack:
    image: localstack/localstack:latest
    container_name: localstack_s3_demo
    environment:
      SERVICES: s3
    ports:
      - '127.0.0.1:4566:4566'" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD">version</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">3.9</span><span style="color: #E9F284">&#39;</span></span>
<span class="line"><span style="color: #8BE9FD">services</span><span style="color: #FF79C6">:</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #8BE9FD">localstack</span><span style="color: #FF79C6">:</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD">image</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">localstack/localstack:latest</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD">container_name</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">localstack_s3_demo</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD">environment</span><span style="color: #FF79C6">:</span></span>
<span class="line"><span style="color: #F8F8F2">      </span><span style="color: #8BE9FD">SERVICES</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">s3</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD">ports</span><span style="color: #FF79C6">:</span></span>
<span class="line"><span style="color: #F8F8F2">      </span><span style="color: #FF79C6">-</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">127.0.0.1:4566:4566</span><span style="color: #E9F284">&#39;</span></span></code></pre></div>



<p class="wp-block-paragraph">Start LocalStack container để sử dụng nào:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker-compose up -d" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #50FA7B">docker-compose</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">up</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">-d</span></span></code></pre></div>



<p class="wp-block-paragraph">Tạo mới một s3 bucket với tên &#8220;<em>bucket-demo</em>&#8220;:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker exec -it localstack_s3_demo awslocal s3 mb s3://bucket-demo" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #50FA7B">docker</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">exec</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">-it</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">localstack_s3_demo</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">awslocal</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">s3</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">mb</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">s3://bucket-demo</span></span></code></pre></div>



<h4 id="upload-file-to-s3" class="wp-block-heading"><strong>Upload file to S3 ?</strong></h4>



<p class="wp-block-paragraph">Để demo việc upload lên file tới S3 tôi sử dụng package <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">@aws-sdk/client-s3</mark> cho gần gũi với đại chúng anh em coder, anh em có thể tham khảo đoạn code dưới đây:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="import { S3Client, PutObjectCommand } from &quot;@aws-sdk/client-s3&quot;;
import fs from &quot;fs&quot;;

const S3_AWS_ACCESS_KEY_ID = &quot;dummy&quot;;
const S3_AWS_SECRET_KEY = &quot;dummy&quot;;
const S3_AWS_BUCKET_NAME = &quot;bucket-demo&quot;;
const useLocal = true; // false if not using LocalStack

const client = new S3Client({
  region: &quot;us-east-1&quot;,
  endpoint: useLocal ? &quot;http://127.0.0.1:4566&quot; : undefined,
  credentials: {
    accessKeyId: S3_AWS_ACCESS_KEY_ID,
    secretAccessKey: S3_AWS_SECRET_KEY,
  },
});

const params = {
  Bucket: S3_AWS_BUCKET_NAME,
  Key: &quot;example.jpg&quot;,
  ContentType: &quot;image/jpeg&quot;,
  Body: fs.readFileSync(&quot;./example.jpg&quot;),
  s3ForcePathStyle: true,
};

const command = new PutObjectCommand(params);

try {
  const response = await client.send(command);
  console.log(response);
  console.log(&quot;File uploaded successfully!&quot;);
} catch (error) {
  console.error(error);
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">import</span><span style="color: #F8F8F2"> { S3Client, PutObjectCommand } </span><span style="color: #FF79C6">from</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">@aws-sdk/client-s3</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">import</span><span style="color: #F8F8F2"> fs </span><span style="color: #FF79C6">from</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">fs</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_ACCESS_KEY_ID </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">dummy</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_SECRET_KEY </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">dummy</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_BUCKET_NAME </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">bucket-demo</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> useLocal </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">true</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// false if not using LocalStack</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> client </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6; font-weight: bold">new</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">S3Client</span><span style="color: #F8F8F2">({</span></span>
<span class="line"><span style="color: #F8F8F2">  region</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">us-east-1</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  endpoint</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> useLocal </span><span style="color: #FF79C6">?</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">http://127.0.0.1:4566</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">undefined</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  credentials</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">    accessKeyId</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_ACCESS_KEY_ID,</span></span>
<span class="line"><span style="color: #F8F8F2">    secretAccessKey</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_SECRET_KEY,</span></span>
<span class="line"><span style="color: #F8F8F2">  },</span></span>
<span class="line"><span style="color: #F8F8F2">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> params </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">  Bucket</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_BUCKET_NAME,</span></span>
<span class="line"><span style="color: #F8F8F2">  Key</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">example.jpg</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  ContentType</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">image/jpeg</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  Body</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> fs.</span><span style="color: #50FA7B">readFileSync</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">./example.jpg</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">),</span></span>
<span class="line"><span style="color: #F8F8F2">  s3ForcePathStyle</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">true</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> command </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6; font-weight: bold">new</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">PutObjectCommand</span><span style="color: #F8F8F2">(params);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">try</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> response </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">await</span><span style="color: #F8F8F2"> client.</span><span style="color: #50FA7B">send</span><span style="color: #F8F8F2">(command);</span></span>
<span class="line"><span style="color: #F8F8F2">  console.</span><span style="color: #50FA7B">log</span><span style="color: #F8F8F2">(response);</span></span>
<span class="line"><span style="color: #F8F8F2">  console.</span><span style="color: #50FA7B">log</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">File uploaded successfully!</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #F8F8F2">} </span><span style="color: #FF79C6">catch</span><span style="color: #F8F8F2"> (error) {</span></span>
<span class="line"><span style="color: #F8F8F2">  console.</span><span style="color: #50FA7B">error</span><span style="color: #F8F8F2">(error);</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Start upload file :</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code=" &gt; node upload.js
 
{
  '$metadata': {
    httpStatusCode: 200,
    requestId: 'CE5CQBpI8HEwPsSI4pChERwgSYOvFLIjv5xTPbO9Zg1GLEEp80vN',
    extendedRequestId: 'MzRISOwyjmnupAC6A5B7CD242F7B57/JypPGXLh0OVFGcJaaO3KW/hRAqKOpIEEp',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  ETag: '&quot;2067c44cf823bd1b9c2cb66ba8f407e2&quot;'
}
File uploaded successfully!
 " style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">&gt;</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">node</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">upload.js</span></span>
<span class="line"><span style="color: #F8F8F2"> </span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #50FA7B">&#39;$metadata&#39;</span><span style="color: #8BE9FD">:</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">httpStatusCode:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">200</span><span style="color: #F1FA8C">,</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">requestId:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">CE5CQBpI8HEwPsSI4pChERwgSYOvFLIjv5xTPbO9Zg1GLEEp80vN</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">,</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">extendedRequestId:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">MzRISOwyjmnupAC6A5B7CD242F7B57/JypPGXLh0OVFGcJaaO3KW/hRAqKOpIEEp</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">,</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">cfId:</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">undefined,</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">attempts:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">1</span><span style="color: #F1FA8C">,</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #50FA7B">totalRetryDelay:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">0</span></span>
<span class="line"><span style="color: #F8F8F2">  },</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #50FA7B">ETag:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">&quot;2067c44cf823bd1b9c2cb66ba8f407e2&quot;</span><span style="color: #E9F284">&#39;</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span>
<span class="line"><span style="color: #50FA7B">File</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">uploaded</span><span style="color: #F8F8F2"> </span><span style="color: #F1FA8C">successfully!</span></span>
<span class="line"><span style="color: #F8F8F2"> </span></span></code></pre></div>



<p class="wp-block-paragraph">Sử dụng package<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">@aws-sdk/s3-request-presigner</mark>để lấy presigned URL:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="// getSignedUrl.js

import { S3Client, GetObjectCommand } from &quot;@aws-sdk/client-s3&quot;;
import { getSignedUrl } from &quot;@aws-sdk/s3-request-presigner&quot;;

const S3_AWS_ACCESS_KEY_ID = &quot;dummy&quot;;
const S3_AWS_SECRET_KEY = &quot;dummy&quot;;
const S3_AWS_BUCKET_NAME = &quot;bucket-demo&quot;;
const useLocal = true;

const client = new S3Client({
  region: &quot;us-east-1&quot;,
  endpoint: useLocal ? &quot;http://127.0.0.1:4566&quot; : undefined,
  credentials: {
    accessKeyId: S3_AWS_ACCESS_KEY_ID,
    secretAccessKey: S3_AWS_SECRET_KEY,
  },
});

const params = {
  Bucket: S3_AWS_BUCKET_NAME,
  Key: &quot;example.jpg&quot;,
  Expires: 3600, // The URL will expire in 3600 seconds.
};

const command = new GetObjectCommand(params);

try {
  const url = await getSignedUrl(client, command);
  console.log(url);
} catch (error) {
  console.error(error);
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #6272A4">// getSignedUrl.js</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">import</span><span style="color: #F8F8F2"> { S3Client, GetObjectCommand } </span><span style="color: #FF79C6">from</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">@aws-sdk/client-s3</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">import</span><span style="color: #F8F8F2"> { getSignedUrl } </span><span style="color: #FF79C6">from</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">@aws-sdk/s3-request-presigner</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_ACCESS_KEY_ID </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">dummy</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_SECRET_KEY </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">dummy</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> S3_AWS_BUCKET_NAME </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">bucket-demo</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> useLocal </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">true</span><span style="color: #F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> client </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6; font-weight: bold">new</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">S3Client</span><span style="color: #F8F8F2">({</span></span>
<span class="line"><span style="color: #F8F8F2">  region</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">us-east-1</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  endpoint</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> useLocal </span><span style="color: #FF79C6">?</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">http://127.0.0.1:4566</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">undefined</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  credentials</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">    accessKeyId</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_ACCESS_KEY_ID,</span></span>
<span class="line"><span style="color: #F8F8F2">    secretAccessKey</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_SECRET_KEY,</span></span>
<span class="line"><span style="color: #F8F8F2">  },</span></span>
<span class="line"><span style="color: #F8F8F2">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> params </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">  Bucket</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> S3_AWS_BUCKET_NAME,</span></span>
<span class="line"><span style="color: #F8F8F2">  Key</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&quot;</span><span style="color: #F1FA8C">example.jpg</span><span style="color: #E9F284">&quot;</span><span style="color: #F8F8F2">,</span></span>
<span class="line"><span style="color: #F8F8F2">  Expires</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">3600</span><span style="color: #F8F8F2">, </span><span style="color: #6272A4">// The URL will expire in 3600 seconds.</span></span>
<span class="line"><span style="color: #F8F8F2">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> command </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6; font-weight: bold">new</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">GetObjectCommand</span><span style="color: #F8F8F2">(params);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #FF79C6">try</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> url </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">await</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">getSignedUrl</span><span style="color: #F8F8F2">(client, command);</span></span>
<span class="line"><span style="color: #F8F8F2">  console.</span><span style="color: #50FA7B">log</span><span style="color: #F8F8F2">(url);</span></span>
<span class="line"><span style="color: #F8F8F2">} </span><span style="color: #FF79C6">catch</span><span style="color: #F8F8F2"> (error) {</span></span>
<span class="line"><span style="color: #F8F8F2">  console.</span><span style="color: #50FA7B">error</span><span style="color: #F8F8F2">(error);</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Get presigned URL:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&gt; node getSignedUrl.js

http://127.0.0.1:4566/bucket-demo/example.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=dummy%2F20231008%2Fus-east-1%2Fs3%2Faws4_request&amp;X-Amz-Date=20231008T100241Z&amp;X-Amz-Expires=900&amp;X-Amz-Signature=73d10095729f1d47feee9926aa0c0d31d086c979206f93b475265bee2dc4cd4f&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">&gt;</span><span style="color: #F8F8F2"> node getSignedUrl.js</span></span>
<span class="line"></span>
<span class="line"><span style="color: #50FA7B">http://127.0.0.1:4566/bucket-demo/example.jpg?X-Amz-Algorithm</span><span style="color: #F8F8F2">=AWS4-HMAC-SHA256&amp;</span><span style="color: #BD93F9">X-Amz-Content-Sha256</span><span style="color: #FF79C6">=</span><span style="color: #F1FA8C">UNSIGNED-PAYLOAD</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">X-Amz-Credential</span><span style="color: #FF79C6">=</span><span style="color: #F1FA8C">dummy%2F20231008%2Fus-east-1%2Fs3%2Faws4_request</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">X-Amz-Date</span><span style="color: #FF79C6">=</span><span style="color: #BD93F9">20231008</span><span style="color: #F1FA8C">T100241Z</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">X-Amz-Expires</span><span style="color: #FF79C6">=</span><span style="color: #BD93F9">900</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">X-Amz-Signature</span><span style="color: #FF79C6">=</span><span style="color: #BD93F9">73</span><span style="color: #F1FA8C">d10095729f1d47feee9926aa0c0d31d086c979206f93b475265bee2dc4cd4f</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">X-Amz-SignedHeaders</span><span style="color: #FF79C6">=</span><span style="color: #F1FA8C">host</span><span style="color: #F8F8F2">&amp;</span><span style="color: #BD93F9">x-id</span><span style="color: #FF79C6">=</span><span style="color: #F1FA8C">GetObject</span></span></code></pre></div>



<p class="wp-block-paragraph">Đơn giản thực sự đúng không anh em ! Nếu các đồng chí có bất kỳ thắc mắc hay chạy các đoạn script trên có bất cứ bug nào hãy comment cho mình được biết nha ! Cảm ơn các đồng dâm ! Thân ái và hẹn gặp lại !</p>
<p>The post <a href="https://blog.tomosia.com.vn/su-dung-localstack-de-gia-lap-upload-file-s3/">Sử dụng localstack để giả lập upload file s3</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/su-dung-localstack-de-gia-lap-upload-file-s3/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
	</channel>
</rss>
