const sharp = require('sharp')
export async function GET() {
/**
* TODO:
* - Download image from Unsplash
* - Convert to webp
* - upload img to R2
*/
//download image from unsplash
const res = await fetch(`https://api.unsplash.com/photos/random/?client_id=[redacted]`)
const data = await res.json();
const download_url = data.links.download_location;
console.log("download url: ", download_url)
const photo = await fetch (`${download_url}/?client_id=[redacted]`)
const photo_data = await photo.json();
const photo_url = photo_data.url;
console.log("photo_url: ", photo_url)
const actualPhoto = await fetch(photo_url)
const actualPhotoData = await actualPhoto.arrayBuffer()
console.log("actual photo data: ", actualPhotoData)
//convert to webp using sharp
const imageToWebp = await sharp(actualPhotoData).webp().toFile('image.webp')
//upload to R2
//since i'm not going to actually create an R2 bucket for this example, I'm just going to pretend that I did it.
//what i would have done though, is make my own bucket, and then use the R2 API to upload the image to the bucket
}
This required making use of Unsplash's API as a starting point. The API provides a route to download a random image, which worked well for the example and added some fun to it. That route was at https://api.unsplash.com/photos/random, and it would give a whole bunch of information about the image that was picked. What was most important, was the download_location param that was found in the links part of the response from that endpoint. I figured to use that parameter specifically thanks to this article. Doing this gave me a URL to the image. I used .arrayBuffer() from that response to get that actual data from the image and saved that to a variable called actualPhotoData.
I learned that a library you can use for image manipulation is Sharp and it makes file type conversions and other image manipulations pretty easy to use. I added it to the project, and then was able to pass actualPhotoDatainto the sharp object constructor. By the way, figuring out what exactly to pass in to the constructor was clear when I looked at the constructor part of the docs and saw that an ArrayBuffer was an acceptable type as an input. It's straightforward from this line of code how I got my resulting image (that I would've then uploaded to R2):
const imageToWebp = await sharp(actualPhotoData).webp().toFile('image.webp')
Though I didn't set up the R2 database, I would've then looked into the R2 API to figure out how to upload that image file. At the end of the last step, I had a file called "image.webp" in the local directory of my project.
Ways that this concept could be expanded into a functioning app could be a random meme generator- or some other type of generator that relies on using an image and potentially saving it. Generating an image from an image store like Unsplash would be a great first step, and then immediately uploading an optimized WebP version of the image allows for it to be saved more efficiently for further use.