The Best Fluffy Pancakes recipe you will fall in love with. Full of tips and tricks to help you make the best pancakes.

Nuxt 圖檔快取儲存機制

今天做了一個職缺精選的圖片區塊,圖片原本是從後端請求而來,但是後來想到如果這個圖片都沒變動過,他能不能直接取得nuxt上面快取的圖片就好,不要都要跟後端要資料呢?

所以設計了一個機制,資料中帶有一個image_uuid的欄位,用它來當作資料的比對碼,當我後端更新圖片時,就同時更新這個uuid碼。到前端時用image_uuid做為圖片的檔案名稱,並到指定的位子取得圖片,如果現在還沒有快取的圖片,或是因為圖片更新導致image_uuid比對不上,就會觸發@error事件,這時候再去跟後端要一次資料,儲存圖片之後重新再render一次圖片,這樣就完成了~


const defaultImageUrl = '/web/_nuxt/assets/images/maintain.png';

const onImageError = async (index) => {
  const row = featuredJobs.value[index]
  row.imageUrl = defaultImageUrl;
  try {
    await fetchAndStoreImage(row)
    row.imageUrl = getImageUrl(row);
  }
  catch (error) {
    row.imageUrl = defaultImageUrl;
  }
};

const getImageUrl = (row, isDefault) => {
  let url = defaultImageUrl
  try {
    if (row?.image_uuid && row?.image && row.image.split('.')[1]) {
      url = cacheImgUrl + row.id + '/' + row.image_uuid + '.' + row.image.split('.')[1]
    }
  }
  catch (error) { }
  return url
}

const fetchAndStoreImage = async (job) => {
  try {
    const response = await axios.get(`${backendImageUrl}${job.id}`, { responseType: 'blob' });

    if (response.status !== 200) {
      throw new Error(`Failed to fetch image: ${response.statusText}`);
    }

    const imageBlob = response.data;
    const imageType = imageBlob.type.split('/')[1]
    const imageFileName = `${job.image_uuid}.${imageType}`;

    const formData = new FormData();
    formData.append('file', imageBlob, imageFileName);
    formData.append('job_id', job.id);

    const uploadResponse = await $fetch('/api/upload_featured_job_image', {
      method: 'POST',
      body: formData,
    });
    if (!uploadResponse.status == 200) {
      throw new Error('Failed to upload image');
    }
  } catch (error) {
    console.error('Error in fetchAndStoreImage:', error);
    throw error; // 將錯誤傳遞回上層
  }
};
</script>
// 前端程式碼擷取,其中包含一些錯誤處裡的邏輯
// server/api/upload.ts
import path from 'path';
import fs from 'fs';

export default defineEventHandler(async (event) => {
  const params = await readMultipartFormData(event);
  const data = {};
  let file = null;

  params?.forEach((item) => {
    if (item.type) {
      file = item;
    } else {
      data[item.name] = item.data
    }
  });

  if (!data?.job_id && !file) {
    throw new Error('Missing job_id field');
  }

  const jobId = data.job_id;
  const directory = path.join(process.cwd(), `/assets/images/featured_job/${jobId}/`);
  const filePath = path.join(directory, file.filename);

  if (fs.existsSync(directory)) {
    fs.readdirSync(directory).forEach((file) => {
      const filePath = path.join(directory, file);
      if (fs.statSync(filePath).isFile()) {
        fs.unlinkSync(filePath);
      }
    });
  } else {
    fs.mkdirSync(directory, { recursive: true })
  }

  fs.writeFileSync(filePath, file.data);

  return {
    status: 200,
    message: 'Upload successful',
    data,
  };
});
// 接收圖片上傳nuxt server檔案

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *