تقنية

كيفية إنشاء نموذج HTML لتحميل الملفات إلى Google Cloud Storage


لنكتب تطبيق ويب بسيطًا يسمح للمستخدمين بتحميل الملفات إلى Google Cloud Storage دون مصادقة. سيحتوي موقع العميل الخاص بالتطبيق على نموذج HTML يحتوي على حقل إدخال واحد أو أكثر. جانب الخادم هو تطبيق Node.js الذي سيتولى تحميل الملف. يمكن نشر التطبيق في Google Cloud Run أو Firebase Function أو كوظيفة Google Cloud.

نموذج HTML

يشتمل نموذج HTML الخاص بنا على حقل اسم وحقل إدخال ملف يقبل ملفات الصور فقط. كلا الحقلين مطلوبان.

عندما يرسل المستخدم النموذج، يتم إرسال بيانات النموذج إلى الخادم، مشفرة كبيانات متعددة الأجزاء/نموذج، باستخدام Fetch API. سيقوم الخادم بالتحقق من صحة بيانات النموذج وإذا كان النموذج صالحًا، فسوف يقوم بتحميل الملف إلى Google Cloud Storage.

<form method="post" enctype="multipart/form-data">
  <input type="text" name="name" id="name" placeholder="Your name" required />
  <input type="file" name="image" accept="image/*" required />
  <input type="submit" value="Submit Form" />
</form>

<script>
  const formElem = document.querySelector('form');
  formElem.addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append('name', e.target[0].value);
    formData.append('file', e.target[1].files[0]);
    const response = await fetch('/submitform', {
      method: 'POST',
      body: formData,
    });
    const data = await response.text();
    return data;
  });
</script>

تطبيق Node.js

سيكون لتطبيقنا طريقين:

  1. مسار الصفحة الرئيسية (/) الذي سيعرض النموذج.
  2. مسار نموذج الإرسال الذي سيتعامل مع تحميل الملف.
// index.js
const express = require('express');
const router = require('./router');

const app = express();

app.get("https://www.labnol.org/", (_, res) => {
  res.sendFile(`${__dirname}/index.html`);
});

app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
app.use(router);

app.listen(process.env.PORT || 8080, async () => {
  console.log('listening on port 8080');
});

نظرًا لأن خادم Express لا يمكنه التعامل مع بيانات النموذج متعددة الأجزاء، فإننا نستخدم البرنامج الوسيط Multer لتحليل بيانات النموذج التي تتضمن كلاً من محتوى النص والبيانات الثنائية. نقوم أيضًا بتجاهل اسم الملف الأصلي للملف الذي تم تحميله وقمنا بتعيين اسم الملف الفريد الخاص بنا والذي تم إنشاؤه من ملف uuid مكتبة.

// router.js
const express = require('express');
const { Storage } = require('@google-cloud/storage');
const { v4: uuidv4 } = require('uuid');
const multer = require('multer');

const storage = new Storage();
const router = express.Router();
const upload = multer();

router.post('/submit', upload.single('file'), async (req, res) => {
  const { name } = req.body;
  const { mimetype, originalname, size } = req.file;
  if (!mimetype || mimetype.split("https://www.labnol.org/")[0] !== 'image') {
    return res.status(400).send('Only images are allowed');
  }
  if (size > 10485760) {
    return res.status(400).send('Image must be less than 10MB');
  }
  const bucketName = '<<GOOGLE_CLOUD_STORAGE_BUCKET_NAME>>';
  const fileExtension = originalname.split('.').pop();
  const fileName = `${uuidv4()}.${fileExtension}`;
  const file = storage.bucket(bucketName).file(fileName);
  await file.save(req.file.buffer, {
    contentType: mimetype,
    resumable: false,
    public: true,
  });
  const url = `https://storage.googleapis.com/${bucketName}/${fileName}`;
  console.log(`File uploaded by ${name}`, url);
  return res.status(200).send(url);
});

module.exports = router;

استخدام وظائف Firebase

إذا كنت تخطط لنشر تطبيق تحميل الملفات الخاص بك إلى وظائف Firebase، فستلزم بعض التغييرات نظرًا لأن برنامجنا الوسيط Multer غير متوافق مع وظائف Firebase.

كحل بديل، يمكننا تحويل الصورة إلى base64 من جانب العميل ثم تحميل الصورة إلى Google Cloud Storage. وبدلاً من ذلك، يمكنك استخدام Busboy وسيطة لتحليل بيانات النموذج.

const convertBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.onload = () => {
      const base64String = fileReader.result;
      const base64Image = base64String.split(';base64,').pop();
      resolve(base64Image);
    };
    fileReader.onerror = (error) => {
      reject(error);
    };
  });
};

const handleUpload = async (file) => {
  const base64 = await convertBase64(file);
  const { type, size, name } = file;

  const response = await fetch('/submitform', {
    headers: { 'Content-Type': 'application/json' },
    method: 'POST',
    body: JSON.stringify({ type, size, name, base64 }),
  });

  const url = await response.text();
  console.log(`File uploaded by ${name}`, url);
};

يجب تعديل معالج نموذج الإرسال لتحويل صورة base64 إلى مخزن مؤقت ثم تحميل الصورة إلى Google Cloud Storage.

router.post('/upload', async (req, res) => {
  const { name, type, size, base64 } = req.body;
  const buffer = Buffer.from(base64, 'base64');
  await file.save(buffer, {
    contentType: type,
    resumable: false,
    public: true,
  });
  return res.send(`File uploaded`);
});

كورس للطلبات عبر الأصل

إذا كنت تعرض النموذج في مجال مختلف عن معالج النموذج، فستحتاج إلى إضافة ملف cors الوسيطة لتطبيقك.

const cors = require('cors')({ origin: true });
app.use(cors);

يجب عليك تعيين سياسة التحكم في الوصول الخاصة بحاوية Google Cloud Storage إلى “دقيقة الحبيبات” وليس “موحدة”. عندما يتم تحميل الملفات الفردية إلى Cloud Storage، فإنها تكون عامة ولكن مجلد الحاوية يظل خاصًا.



Source link


اكتشاف المزيد من مرابع التكنولوجيا

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى

اكتشاف المزيد من مرابع التكنولوجيا

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading