# رفع الملفات إلى متجر المتجهات

{% openapi src="<https://4065521171-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKV4TZLzR1jCpM5coRezn%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media&token=5e84eb03-c48b-4980-9792-73172ea64dd4>" path="/vector-stores/{vector-store-id}/documents/upload" method="post" %}
[rememberizer\_openapi.yml](https://4065521171-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKV4TZLzR1jCpM5coRezn%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media\&token=5e84eb03-c48b-4980-9792-73172ea64dd4)
{% endopenapi %}

## طلبات مثال

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST \
  https://api.rememberizer.ai/api/v1/vector-stores/vs_abc123/documents/upload \
  -H "x-api-key: YOUR_API_KEY" \
  -F "files=@/path/to/document1.pdf" \
  -F "files=@/path/to/document2.docx"
```

{% hint style="info" %}
استبدل `YOUR_API_KEY` بمفتاح API الفعلي لمتجر المتجهات الخاص بك، و `vs_abc123` بمعرف متجر المتجهات الخاص بك، وقدم المسارات إلى ملفاتك المحلية.
{% endhint %}
{% endtab %}

{% tab title="JavaScript" %}

```javascript
const uploadFiles = async (vectorStoreId, files) => {
  const formData = new FormData();
  
  // إضافة ملفات متعددة إلى بيانات النموذج
  for (const file of files) {
    formData.append('files', file);
  }
  
  const response = await fetch(`https://api.rememberizer.ai/api/v1/vector-stores/${vectorStoreId}/documents/upload`, {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY'
      // ملاحظة: لا تقم بتعيين رأس Content-Type، سيتم تعيينه تلقائيًا مع الحدود الصحيحة
    },
    body: formData
  });
  
  const data = await response.json();
  console.log(data);
};

// مثال على الاستخدام مع عنصر إدخال الملف
const fileInput = document.getElementById('fileInput');
uploadFiles('vs_abc123', fileInput.files);
```

{% hint style="info" %}
استبدل `YOUR_API_KEY` بمفتاح API الفعلي لمتجر المتجهات الخاص بك و `vs_abc123` بمعرف متجر المتجهات الخاص بك.
{% endhint %}
{% endtab %}

{% tab title="Python" %}

```python
import requests

def upload_files(vector_store_id, file_paths):
    headers = {
        "x-api-key": "YOUR_API_KEY"
    }
    
    files = [('files', (file_path.split('/')[-1], open(file_path, 'rb'))) for file_path in file_paths]
    
    response = requests.post(
        f"https://api.rememberizer.ai/api/v1/vector-stores/{vector_store_id}/documents/upload",
        headers=headers,
        files=files
    )
    
    data = response.json()
    print(data)

upload_files('vs_abc123', ['/path/to/document1.pdf', '/path/to/document2.docx'])
```

{% hint style="info" %}
استبدل `YOUR_API_KEY` بمفتاح API الفعلي لمتجر المتجهات الخاص بك، و `vs_abc123` بمعرف متجر المتجهات الخاص بك، وقدم المسارات إلى ملفاتك المحلية.
{% endhint %}
{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'

def upload_files(vector_store_id, file_paths)
  uri = URI("https://api.rememberizer.ai/api/v1/vector-stores/#{vector_store_id}/documents/upload")
  
  # إنشاء كائن HTTP جديد
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  # إنشاء طلب multipart-form
  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = 'YOUR_API_KEY'
  
  # إنشاء حد multipart
  boundary = "RubyFormBoundary#{rand(1000000)}"
  request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
  
  # بناء جسم الطلب
  body = []
  file_paths.each do |file_path|
    file_name = File.basename(file_path)
    file_content = File.read(file_path, mode: 'rb')
    
    body << "--#{boundary}\r\n"
    body << "Content-Disposition: form-data; name=\"files\"; filename=\"#{file_name}\"\r\n"
    body << "Content-Type: #{get_content_type(file_name)}\r\n\r\n"
    body << file_content
    body << "\r\n"
  end
  body << "--#{boundary}--\r\n"
  
  request.body = body.join
  
  # إرسال الطلب
  response = http.request(request)
  
  # تحليل وإرجاع الاستجابة
  JSON.parse(response.body)
end
```

## طريقة مساعدة لتحديد نوع المحتوى

def get\_content\_type(filename) ext = File.extname(filename).downcase case ext when '.pdf' then 'application/pdf' when '.doc' then 'application/msword' when '.docx' then 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' when '.txt' then 'text/plain' when '.md' then 'text/markdown' when '.json' then 'application/json' else 'application/octet-stream' end end

## مثال على الاستخدام

result = upload\_files('vs\_abc123', \['/path/to/document1.pdf', '/path/to/document2.docx']) puts result

````

{% hint style="info" %}
استبدل `YOUR_API_KEY` بمفتاح API الخاص بك لـ Vector Store، و `vs_abc123` بمعرف Vector Store الخاص بك، وقدم المسارات إلى ملفاتك المحلية.
{% endhint %}
{% endtab %}
{% endtabs %}

## معلمات المسار

| المعلمة | النوع | الوصف |
|-----------|------|-------------|
| vector-store-id | سلسلة | **مطلوب.** معرف متجر المتجهات لتحميل الملفات إليه. |

## جسم الطلب

تقبل هذه النقطة النهائية طلب `multipart/form-data` مع ملف واحد أو أكثر في حقل `files`.

## صيغة الاستجابة

```json
{
  "documents": [
    {
      "id": 1234,
      "name": "document1.pdf",
      "type": "application/pdf",
      "size": 250000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    },
    {
      "id": 1235,
      "name": "document2.docx",
      "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "size": 180000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    }
  ],
  "errors": []
}
````

إذا فشلت بعض الملفات في التحميل، فسيتم إدراجها في مصفوفة `errors`:

```json
{
  "documents": [
    {
      "id": 1234,
      "name": "document1.pdf",
      "type": "application/pdf",
      "size": 250000,
      "status": "processing",
      "created": "2023-06-15T10:15:00Z",
      "vector_store": "vs_abc123"
    }
  ],
  "errors": [
    {
      "file": "document2.docx",
      "error": "تنسيق الملف غير مدعوم"
    }
  ]
}
```

### المصادقة

تتطلب هذه النقطة النهائية المصادقة باستخدام مفتاح API في رأس `x-api-key`.

### تنسيقات الملفات المدعومة

* PDF (`.pdf`)
* Microsoft Word (`.doc`, `.docx`)
* Microsoft Excel (`.xls`, `.xlsx`)
* Microsoft PowerPoint (`.ppt`, `.pptx`)
* ملفات نصية (`.txt`)
* Markdown (`.md`)
* JSON (`.json`)
* HTML (`.html`, `.htm`)

### حدود حجم الملف

* حد حجم الملف الفردي: 50MB
* حد حجم الطلب الإجمالي: 100MB
* الحد الأقصى لعدد الملفات في كل طلب: 20

### ردود الخطأ

| رمز الحالة | الوصف                                                   |
| ---------- | ------------------------------------------------------- |
| 400        | طلب غير صحيح - لم يتم تقديم ملفات أو تنسيق طلب غير صالح |
| 401        | غير مصرح - مفتاح API غير صالح أو مفقود                  |
| 404        | غير موجود - لم يتم العثور على متجر المتجهات             |
| 413        | الحمولة كبيرة جدًا - الملفات تتجاوز حد الحجم            |
| 415        | نوع الوسائط غير مدعوم - تنسيق الملف غير مدعوم           |
| 500        | خطأ في الخادم الداخلي                                   |
| 207        | حالة متعددة - تم تحميل بعض الملفات بنجاح، لكن فشلت أخرى |

### حالة المعالجة

يتم قبول الملفات في البداية بحالة `processing`. يمكنك التحقق من حالة معالجة الوثائق باستخدام نقطة النهاية [الحصول على قائمة بالوثائق في متجر المتجهات](https://docs.rememberizer.ai/ar/mward-almtwryn/api-docs/vector-store/get-a-list-of-documents-in-a-vector-store). ستكون الحالة النهائية واحدة من:

* `done`: تم معالجة الوثيقة بنجاح
* `error`: حدث خطأ أثناء المعالجة
* `processing`: لا تزال الوثيقة قيد المعالجة

تعتمد مدة المعالجة على حجم الملف وتعقيده. تتراوح مدة المعالجة النموذجية بين 30 ثانية إلى 5 دقائق لكل وثيقة.

### العمليات الدفعة

لرفع عدة ملفات إلى متجر المتجهات الخاص بك بكفاءة، يدعم Rememberizer العمليات الدفعة. تساعد هذه الطريقة في تحسين الأداء عند التعامل مع أعداد كبيرة من الوثائق.

#### تنفيذ تحميل دفعة

{% tabs %} {% tab title="Python" %}

```python
import os
import requests
import time
import concurrent.futures
from pathlib import Path

def batch_upload_to_vector_store(vector_store_id, folder_path, batch_size=5, file_types=None):
    """
    تحميل جميع الملفات من دليل إلى متجر المتجهات على دفعات
    
    Args:
        vector_store_id: معرف متجر المتجهات
        folder_path: مسار المجلد الذي يحتوي على الملفات المراد تحميلها
        batch_size: عدد الملفات التي سيتم تحميلها في كل دفعة
        file_types: قائمة اختيارية من امتدادات الملفات للتصفية (مثل: ['.pdf', '.docx'])
        
    Returns:
        قائمة بنتائج التحميل
    """
    api_key = "YOUR_API_KEY"
    headers = {"x-api-key": api_key}
    
    # الحصول على قائمة الملفات في الدليل
    files = []
    for entry in os.scandir(folder_path):
        if entry.is_file():
            file_path = Path(entry.path)
            # تصفية حسب امتداد الملف إذا تم تحديده
            if file_types is None or file_path.suffix.lower() in file_types:
                files.append(file_path)
    
    print(f"تم العثور على {len(files)} ملف لتحميله")
    results = []
    
    # معالجة الملفات على دفعات
    for i in range(0, len(files), batch_size):
        batch = files[i:i+batch_size]
        print(f"معالجة الدفعة {i//batch_size + 1}/{(len(files) + batch_size - 1)//batch_size}: {len(batch)} ملفات")
        
        # تحميل الدفعة
        upload_files = []
        for file_path in batch:
            upload_files.append(('files', (file_path.name, open(file_path, 'rb'))))
        
        try:
            response = requests.post(
                f"https://api.rememberizer.ai/api/v1/vector-stores/{vector_store_id}/documents/upload",
                headers=headers,
                files=upload_files
            )
            
            # إغلاق جميع مقبضات الملفات
            for _, (_, file_obj) in upload_files:
                file_obj.close()
            
            if response.status_code in (200, 201, 207):
                batch_result = response.json()
                results.append(batch_result)
                print(f"تم تحميل الدفعة بنجاح - {len(batch_result.get('documents', []))} مستندات تمت معالجتها")
                
                # التحقق من الأخطاء
                if batch_result.get('errors') and len(batch_result['errors']) > 0:
                    print(f"تم مواجهة أخطاء: {len(batch_result['errors'])}")
                    for error in batch_result['errors']:
                        print(f"- {error['file']}: {error['error']}")
            else:
                print(f"فشل تحميل الدفعة برمز الحالة {response.status_code}: {response.text}")
                results.append({"error": f"فشل الدفعة: {response.text}"})
                
        except Exception as e:
            print(f"استثناء أثناء تحميل الدفعة: {str(e)}")
            results.append({"error": str(e)})
            
            # إغلاق أي مقبضات ملفات متبقية في حالة حدوث استثناء
            for _, (_, file_obj) in upload_files:
                try:
                    file_obj.close()
                except:
                    pass
        
        # تحديد معدل - توقف بين الدفعات
        if i + batch_size < len(files):
            print("توقف قبل الدفعة التالية...")
            time.sleep(2)
    
    return results

# مثال للاستخدام
results = batch_upload_to_vector_store(
    'vs_abc123',
    '/path/to/documents/folder',
    batch_size=5,
    file_types=['.pdf', '.docx', '.txt']
)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
/**
 * رفع الملفات إلى متجر المتجهات على دفعات
 * 
 * @param {string} vectorStoreId - معرف متجر المتجهات
 * @param {FileList|File[]} files - الملفات المراد رفعها
 * @param {Object} options - خيارات التكوين
 * @returns {Promise<Array>} - قائمة بنتائج الرفع
 */
async function batchUploadToVectorStore(vectorStoreId, files, options = {}) {
  const {
    batchSize = 5,
    delayBetweenBatches = 2000,
    onProgress = null
  } = options;
  
  const apiKey = 'YOUR_API_KEY';
  const results = [];
  const fileList = Array.from(files);
  const totalBatches = Math.ceil(fileList.length / batchSize);
  
  console.log(`التحضير لرفع ${fileList.length} ملف في ${totalBatches} دفعات`);
  
  // معالجة الملفات على دفعات
  for (let i = 0; i < fileList.length; i += batchSize) {
    const batch = fileList.slice(i, i + batchSize);
    const batchNumber = Math.floor(i / batchSize) + 1;
    
    console.log(`معالجة الدفعة ${batchNumber}/${totalBatches}: ${batch.length} ملفات`);
    
    if (onProgress) {
      onProgress({
        currentBatch: batchNumber,
        totalBatches: totalBatches,
        filesInBatch: batch.length,
        totalFiles: fileList.length,
        completedFiles: i
      });
    }
    
    // إنشاء FormData لهذه الدفعة
    const formData = new FormData();
    batch.forEach(file => {
      formData.append('files', file);
    });
    
    try {
      const response = await fetch(
        `https://api.rememberizer.ai/api/v1/vector-stores/${vectorStoreId}/documents/upload`,
        {
          method: 'POST',
          headers: {
            'x-api-key': apiKey
          },
          body: formData
        }
      );
      
      if (response.ok) {
        const batchResult = await response.json();
        results.push(batchResult);
        
        console.log(`تم رفع الدفعة بنجاح - ${batchResult.documents?.length || 0} مستندات تمت معالجتها`);
        
        // التحقق من الأخطاء
        if (batchResult.errors && batchResult.errors.length > 0) {
          console.warn(`تمت مواجهة أخطاء: ${batchResult.errors.length}`);
          batchResult.errors.forEach(error => {
            console.warn(`- ${error.file}: ${error.error}`);
          });
        }
      } else {
        console.error(`فشل رفع الدفعة مع الحالة ${response.status}: ${await response.text()}`);
        results.push({ error: `فشلت الدفعة مع الحالة: ${response.status}` });
      }
    } catch (error) {
      console.error(`استثناء أثناء رفع الدفعة: ${error.message}`);
      results.push({ error: error.message });
    }
    
    // إضافة تأخير بين الدفعات لتجنب تحديد المعدل
    if (i + batchSize < fileList.length) {
      console.log(`توقف لمدة ${delayBetweenBatches}ms قبل الدفعة التالية...`);
      await new Promise(resolve => setTimeout(resolve, delayBetweenBatches));
    }
  }
  
  console.log(`اكتمل الرفع. تمت معالجة ${fileList.length} ملفات.`);
  return results;
}

// مثال للاستخدام مع عنصر إدخال الملفات
document.getElementById('upload-button').addEventListener('click', async () => {
  const fileInput = document.getElementById('file-input');
  const vectorStoreId = 'vs_abc123';
  
  const progressBar = document.getElementById('progress-bar');
  
  try {
    const results = await batchUploadToVectorStore(vectorStoreId, fileInput.files, {
      batchSize: 5,
      onProgress: (progress) => {
        // تحديث واجهة المستخدم للتقدم
        const percentage = Math.round((progress.completedFiles / progress.totalFiles) * 100);
        progressBar.style.width = `${percentage}%`;
        progressBar.textContent = `${percentage}% (دفعة ${progress.currentBatch}/${progress.totalBatches})`;
      }
    });
    
    console.log('نتائج الرفع المكتملة:', results);
  } catch (error) {
    console.error('فشل الرفع:', error);
  }
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'
require 'mime/types'

# رفع الملفات إلى متجر المتجهات على دفعات
#
# @param vector_store_id [String] معرف متجر المتجهات
# @param folder_path [String] مسار المجلد الذي يحتوي على الملفات المراد تحميلها
# @param batch_size [Integer] عدد الملفات التي سيتم تحميلها في كل دفعة
# @param file_types [Array<String>] مصفوفة اختيارية من امتدادات الملفات للتصفية بواسطة
# @param delay_between_batches [Float] ثوانٍ للانتظار بين الدفعات
# @return [Array] قائمة نتائج التحميل
def batch_upload_to_vector_store(vector_store_id, folder_path, batch_size: 5, file_types: nil, delay_between_batches: 2.0)
  api_key = 'YOUR_API_KEY'
  results = []
  
  # الحصول على قائمة الملفات في الدليل
  files = Dir.entries(folder_path)
    .select { |f| File.file?(File.join(folder_path, f)) }
    .select { |f| file_types.nil? || file_types.include?(File.extname(f).downcase) }
    .map { |f| File.join(folder_path, f) }
  
  puts "تم العثور على #{files.count} ملفات لتحميلها"
  total_batches = (files.count.to_f / batch_size).ceil
  
  # معالجة الملفات على دفعات
  files.each_slice(batch_size).with_index do |batch, batch_index|
    puts "معالجة الدفعة #{batch_index + 1}/#{total_batches}: #{batch.count} ملفات"
    
    # إعداد طلب HTTP
    uri = URI("https://api.rememberizer.ai/api/v1/vector-stores/#{vector_store_id}/documents/upload")
    request = Net::HTTP::Post.new(uri)
    request['x-api-key'] = api_key
    
    # إنشاء حد للفورم المتعدد الأجزاء
    boundary = "RubyBoundary#{rand(1000000)}"
    request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
    
    # بناء جسم الطلب
    body = []
    batch.each do |file_path|
      file_name = File.basename(file_path)
      mime_type = MIME::Types.type_for(file_path).first&.content_type || 'application/octet-stream'
      
      begin
        file_content = File.binread(file_path)
        
        body << "--#{boundary}\r\n"
        body << "Content-Disposition: form-data; name=\"files\"; filename=\"#{file_name}\"\r\n"
        body << "Content-Type: #{mime_type}\r\n\r\n"
        body << file_content
        body << "\r\n"
      rescue => e
        puts "خطأ في قراءة الملف #{file_path}: #{e.message}"
      end
    end
    body << "--#{boundary}--\r\n"
    
    request.body = body.join
    
    # إرسال الطلب
    begin
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      response = http.request(request)
      
      if response.code.to_i == 200 || response.code.to_i == 201 || response.code.to_i == 207
        batch_result = JSON.parse(response.body)
        results << batch_result
        
        puts "تم تحميل الدفعة بنجاح - #{batch_result['documents']&.count || 0} مستندات تمت معالجتها"
        
        # التحقق من الأخطاء
        if batch_result['errors'] && !batch_result['errors'].empty?
          puts "الأخطاء التي تم مواجهتها: #{batch_result['errors'].count}"
          batch_result['errors'].each do |error|
            puts "- #{error['file']}: #{error['error']}"
          end
        end
      else
        puts "فشل تحميل الدفعة مع رمز الحالة #{response.code}: #{response.body}"
        results << { "error" => "فشل الدفعة: #{response.body}" }
      end
    rescue => e
      puts "استثناء أثناء تحميل الدفعة: #{e.message}"
      results << { "error" => e.message }
    end
    
    # تحديد معدل التحميل - توقف بين الدفعات
    if batch_index < total_batches - 1
      puts "توقف لمدة #{delay_between_batches} ثوانٍ قبل الدفعة التالية..."
      sleep(delay_between_batches)
    end
  end
  
  puts "اكتمل التحميل. تمت معالجة #{files.count} ملفات."
  results
end

# مثال على الاستخدام
results = batch_upload_to_vector_store(
  'vs_abc123',
  '/path/to/documents/folder',
  batch_size: 5,
  file_types: ['.pdf', '.docx', '.txt'],
  delay_between_batches: 2.0
)
```

{% endtab %}
{% endtabs %}

### أفضل الممارسات لتحميل الدفعات

لتحسين الأداء والموثوقية عند تحميل كميات كبيرة من الملفات:

1. **إدارة حجم الدفعة**: احتفظ بأحجام الدفعات بين 5-10 ملفات لتحقيق الأداء الأمثل. عدد كبير جداً من الملفات في طلب واحد يزيد من خطر حدوث مهلات.
2. **تنفيذ تحديد المعدل**: أضف تأخيرات بين الدفعات (يوصى بـ 2-3 ثواني) لتجنب الوصول إلى حدود معدل API.
3. **إضافة منطق إعادة المحاولة عند الخطأ**: بالنسبة للأنظمة الإنتاجية، نفذ منطق إعادة المحاولة للتحميلات الفاشلة مع زيادة زمن الانتظار بشكل أسي.
4. **التحقق من أنواع الملفات**: قم بفرز الملفات مسبقاً لضمان أنها من الأنواع المدعومة قبل محاولة التحميل.
5. **مراقبة تقدم الدفعة**: بالنسبة للتطبيقات الموجهة للمستخدمين، قدم ملاحظات حول تقدم العمليات الخاصة بالدفعات.
6. **التعامل مع النجاح الجزئي**: قد يعيد API رمز الحالة 207 للنجاح الجزئي. تحقق دائماً من حالات الوثائق الفردية.
7. **تنظيف الموارد**: تأكد من إغلاق جميع مقبضات الملفات بشكل صحيح، خاصة عند حدوث أخطاء.
8. **التوازي بحكمة**: بالنسبة للتحميلات الكبيرة جداً (آلاف الملفات)، اعتبر استخدام عمليات دفعات متزامنة متعددة تستهدف متاجر متجهات مختلفة، ثم اجمع النتائج لاحقاً إذا لزم الأمر.
9. **تنفيذ المجموعات الاختبارية**: بالنسبة للبيانات الحرجة، تحقق من سلامة الملفات قبل وبعد التحميل باستخدام المجموعات الاختبارية.
10. **تسجيل النتائج بشكل شامل**: احتفظ بسجلات مفصلة لجميع عمليات التحميل لتسهيل استكشاف الأخطاء.

من خلال اتباع هذه الممارسات الجيدة، يمكنك إدارة إدخال الوثائق على نطاق واسع بكفاءة في متاجر المتجهات الخاصة بك.
