Bookmarklet to download all images on a page with the File System API

My daughter is attending nursery school and every day they post photos of the baby to a special portal so we can see what she has been doing. The web site, is, err, well… functional. However they block the ability to download the photos in their UI, I’ve no clue why, but it’s super frustrating.
I love Bookmarklet because they let me quickly augment a site without having to build a full extension, and this is no exception.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan

<p>My daughter is attending nursery school and every day they post photos of the baby to a special portal so we can see what she has been doing. The web site, is, err, well... functional. However they block the ability to download the photos in their UI, I've no clue why, but it's super frustrating.</p> <p>I love <a href="https://paul.kinlan.me/tags/bookmarklets/">Bookmarklet</a> because they let me quickly augment a site without having to build a full extension, and this is no exception. I knew that the UI gave me access to the actual image so it shouldn't be too complex to find those images, fetch them and save them.</p> <p>Traditionally saving a file from the browser to your machine is <a href="https://www.youtube.com/watch?v=rXLNC8yCRnw&feature=player_detailpage#t=280s">hacky</a>, you create an anchor that links to the image, add a 'download' attribute (optionally with the name of the file), and then simulate a mouse click on it.  </p> <p>I knew that Chromium had added a new <a href="https://web.dev/file-system-access/">File System API</a>, so I wanted to try my hand to see if it would let me batch download a large array of files and then save them to a directory, and it does.</p> <p>The process I chose was as follows:</p> <p>Request the users consent to access a folder (it won't let you pick a system folder such as the photo directory) and get access to the directory handle.</p> <ol> <li>Find all the images on the page</li> <li>Sequentially fetch the images (could have made it parallel but I didn't want to overload their server)</li> <li>Create a file handle in the directory that the user gave the script access to</li> <li>Create a file writer stream</li> <li>Pipe the image to it.</li> <li>Voila. It's saved to disk.</li> </ol> <p>The code for that process is as follows:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-JavaScript" data-lang="JavaScript"><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">run</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> () => { <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">dirHandle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> window.<span style="color:#a6e22e">showDirectoryPicker</span>(); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">imgs</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelectorAll</span>(<span style="color:#e6db74">"img"</span>); <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">imgs</span>.<span style="color:#a6e22e">forEach</span>(<span style="color:#a6e22e">async</span> (<span style="color:#a6e22e">img</span>) => { <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">url</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">img</span>.<span style="color:#a6e22e">src</span>; <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`img-</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">i</span><span style="color:#e6db74">}</span><span style="color:#e6db74">.png`</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>; <span style="color:#66d9ef">try</span> { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">`Fetching </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">url</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">url</span>); <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">`Saving to </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">name</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">file</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">dirHandle</span>.<span style="color:#a6e22e">getFileHandle</span>(<span style="color:#a6e22e">name</span>, { <span style="color:#a6e22e">create</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span> }); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">writable</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">createWritable</span>(); <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">response</span>.<span style="color:#a6e22e">body</span>.<span style="color:#a6e22e">pipeTo</span>(<span style="color:#a6e22e">writable</span>); } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">err</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">err</span>); } }); }; <span style="color:#a6e22e">run</span>(); </code></pre></div><p>I then wrapped it up in a bookmarklet, and now I can download all the images directly to a directory of my choosing, and we are very happy that we can have permanent access to these memories :D</p>


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan


Print Share Comment Cite Upload Translate Updates
APA

Paul Kinlan | Sciencx (2020-12-03T10:45:30+00:00) Bookmarklet to download all images on a page with the File System API. Retrieved from https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/

MLA
" » Bookmarklet to download all images on a page with the File System API." Paul Kinlan | Sciencx - Thursday December 3, 2020, https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/
HARVARD
Paul Kinlan | Sciencx Thursday December 3, 2020 » Bookmarklet to download all images on a page with the File System API., viewed ,<https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/>
VANCOUVER
Paul Kinlan | Sciencx - » Bookmarklet to download all images on a page with the File System API. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/
CHICAGO
" » Bookmarklet to download all images on a page with the File System API." Paul Kinlan | Sciencx - Accessed . https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/
IEEE
" » Bookmarklet to download all images on a page with the File System API." Paul Kinlan | Sciencx [Online]. Available: https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/. [Accessed: ]
rf:citation
» Bookmarklet to download all images on a page with the File System API | Paul Kinlan | Sciencx | https://www.scien.cx/2020/12/03/bookmarklet-to-download-all-images-on-a-page-with-the-file-system-api/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.