تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
نظرة على DropBox SDK و التعامل معها +برنامج رفع و تحميل ملفات
#1
التعامل مع DropBox Api - تحديداً  DropBox SDK  V2


بسم الله الرحمن الرحيم و الصلاة و السلام على سيدنا محمد و على آله و صحبه اجمعين
السلام عليكم و رحمة الله و بركاته
---------------------------------------------
يعد موقع DropBox مقصداً للكثير من المطورين لسهولة التعامل معه في رفع و تحميل الملفات.
و نظراً لاننا نتعامل معه بطريقة او باخرى من خلال برامجنا , ولاننا نفتقد لاي مصدر عربي يسهل علينا التعامل مع Api الخاص بالموقع,
لما يوفره من سهولة في التعامل و يفتح لنا ابواب اوسع لمعالجة امور كنا بحاجتها دوماً.
--------------------------------------------
فقد قررت كتابة هذه المقال لسببين :
الاول : هو اضاءة على الـ Api الخاص بهم للاستفادة منه في برامجنا.
الثاني : ايجاد طريقة اكثر تفاعلاً مع تحميل الملفات للاخوة الذين يتعاملون مع الموقع لتحديث برامجهم.
-------------------------------------------
في البداية ننشئ برنامج و من ثم نقوم  بتحميل المكتبة لبرنامجنا عبر Manage NuGet Packages 





بعد التحميل وفق الصور السابقة ننتقل الى الفورم الرئيسي لدينا .
فكرة البرنامج هو التعامل مع المكتبة وفق مسارين
1- رفع ملفات الى مساحتنا على الموقع.
2- تحميل ملفات من مساحتنا في الموقع.

سندخل الى الموقع اولاً و ننشئ بداخل المساحة مجلد لنرفع بداخله ملفاتنا.
من الجيد اذا كنت ممن لديه عدة برامج و رغبت ان يكون لكل برنامج مجلد خاص ترفع له ملفاتك , ان تنشأ مجلد خاص بكل برنامج.
نبقى مع الصور




سنستخدم المجلد Folder1 لنرفع اليه ملفاتنا كتجربة.

للتعامل مع المكتبة من خلال برنامجك يجب ان تمتلك حق الولوج الى Api الخاص بالموقع لذا يجب عليك ان تمتلك Access Token
سنتعرف الى طريقة انشائها عبر الموقع بخطوات بسيطة عبر الصور.


















الان و بعد ان تحصلت على Access Token  انسخه و احتفظ به لاننا سنحتاجه للتعامل مع المكتبة عبر برنامجنا.
جهز نفسك لننطلق في تجهيز البرنامج...

سننتقل الى الفورم الرئيسي لدينا و نصممه كما في الصورة



قررت تقسيم الشاشة الى قسمين واحد لرفع الملفات و الثاني لتحميل الملفات
شرح الارقام بالترتيب و ما يقابلها من سيناريوهات.

اولاً القسم الخاص برفع الملفات.
1- GetFiles سيكون لدينا اجراء يقوم بفتح مستعرض المجلدات لتحديد الملفات داخل المجلد.
2- DataGridView صمم ليعرض لنا اسماء الملفات داخل المجلد المحدد سابقاً مع معلومات عن حجم كل ملف و رقم النسخة الخاصة به و مسار الملف.
تجدر الاشارة الى ان الملفات التي لا تحمل في خصائصا رقم نسخة سنقوم باعطائها الرقم صفر.
العمود Status داخل القريد من النوع CheckBox سنستخدمه لتحديد الملفات التي نريد رفعها.
3- Upload سيقابله اجراء يقوم بالمرور على الملفات المحددة و رفعها الى مسار محدد داخل مساحتنا , المجلد Folder1 الذي انشأناه سابقاً.
4- يعرض لنا الملف الحالي الجاري رفعه الى المسار المحدد مع عرض نسبة الرفع بالتزامن مع ProgresBar فوقه لتكون العملية تفاعلية.
هذا فيما يخص قسم الرفع.

ثانياً القسم الخاص بالتحميل

5- يعرض لنا المسار الذي يتم التحميل منه.
6- هنا تظهر الملفات التي داخل المسار السابق.
7- Download يقابله اجراء يقوم بالمرور على الملفات السابقة و البدء بتحميلها الى القرص المحلي وفق المسار المعطى داخل الكود.
8- يعرض الملف الحالي الجاري تحميله مع نسبة التقدم بالتوامن مع  ProgresBar  تفاعلي.

كل العمليات من رفع و تحميل تتم بشكل تزامني Asyncronis و تجري اغلب العمليات في مهام منفصلة لكي لا نواجه مشاكل التجميد
حيث يمكنك الرفع و التحميل في نفس الوقت.


ندخل الى محرر الاكواد الخاص بنا لنتعرف الى اهم عناصر المكتبة.


في البداية يلزمنا استيراد الفضاءات التالية لنتمكن من العمل.
PHP كود :
Imports Dropbox.Api
Imports Dropbox
.Api.Files
Imports System
.IO
Imports System
.Net 
سنعمل على القسم الاول الخاص برفع الملفات.
لذا سنقوم بتعريف اجراء يقوم بفتح المستعرض على مكان محدد لنسحب الملفات بداخله الى القريد الخاص بنا.
سنقوم ببناء جدول له نفس اعمدة القريد و نخزن داخله المعلومات القادمة من كل ملف و من ثم نسنده الى القريد.
PHP كود :
   Private Function BuildTable() As DataTable
        Dim Dt 
As New DataTable
        Dim Columns 
As New List(Of DataColumn)
 
       Columns.Add(New DataColumn With {.ColumnName "Status"})
 
       Columns.Add(New DataColumn With {.ColumnName "FileName"})
 
       Columns.Add(New DataColumn With {.ColumnName "FileSize"})
 
       Columns.Add(New DataColumn With {.ColumnName "Version"})
 
       Columns.Add(New DataColumn With {.ColumnName "FilePath"})

 
       Dt.Columns.AddRange(Columns.ToArray)
 
       Return Dt

    End 
Function 
هذا الاجراء المسؤول عن تشكيل الجدول .
الان سيكون لدينا اجراء لجلب الملفات و المرور على كل ملف و نستخلص منه الاسم و الحجم و رقم النسخة و المسار.
PHP كود :
  Dim Dt_FileUpdate As New DataTable
    Private Sub Btn_CollectFiles_Click
(sender As ObjectAs EventArgsHandles Btn_CollectFiles.Click
        If 
(FolderBrowserDialog1.ShowDialog() = DialogResult.OKThen
            Txt_Path
.Text FolderBrowserDialog1.SelectedPath

            Dt_FileUpdate 
BuildTable()
 
           Try
                Me
.Cursor Cursors.WaitCursor
                For Each f In Directory
.GetFiles(Txt_Path.Text"*"IO.SearchOption.AllDirectories)
 
                   Dim _file As New IO.FileInfo(f)

 
                   FileVersionInfo.GetVersionInfo(f)
 
                   Dim myFileVersionInfo As FileVersionInfo FileVersionInfo.GetVersionInfo(f)

 
                   Dim F_Version As String myFileVersionInfo.FileVersion
                    If String
.IsNullOrEmpty(F_VersionThen F_Version 0



                    Dim Row 
As String() = New String() {"False"_file.NameGetSizeKB(f), F_Versionf}
 
                   Dt_FileUpdate.Rows.Add(Row)

 
               Next
                DGV1
.DataSource Dt_FileUpdate
                Me
.Cursor Cursors.Arrow
            Catch ex 
As UnauthorizedAccessException
                MsgBox
(ex.Message)
 
               Me.Cursor Cursors.Arrow
            End 
Try
 
       End If
 
   End Sub 

الاجراء يقوم باضافة معلومات كل ملف الى الجدول Dt_FileUpdate .
الاجراء المسؤول عن حجم كل ملف كالتالي:
PHP كود :
   Public Function GetSizeKB(ByVal filename As String) As Double
        Dim len 
As Double = New FileInfo(filename).Length 1024
        Return String
.Format("{0:0.##}"len)
 
   End Function 
بعد ان تكون القريد قد احتوت على ملفات , يمكننا الان معالجة عملية رفع الملفات.
عند هذه النقطة سنحتاج الى كائنات رئيسية من المكتبة الخاصة بـ DropBox.
الكائن الرئيسي في هذه المكتبة هو DropboxClient , هو المسؤول عن التخاطب و الارسال و الاستقبال...
داخل هذا الكائن سنرسل Access Token التي حصلنا عليها سابقاً , و هي ترسل كوسيطة نصية.
كما و يرتبط هذا الكائن بشكل وثيق مع HttpClient الخاص بالمكتبة Http.HttpClient . و هي المكتبة الحديثة من اطار عمل الدوت نت
وهذه المكتبة صصمت للتعامل بشكل تزامني مع ملفات الانترنت و المواقع.
يحتاج الكائن الى ضبط بعض الاعدادات البسيطة.

نعرف هذه المتغيرات في بداية النموذج.
PHP كود :
   Dim config As DropboxClientConfig
    Dim client 
As DropboxClient
    Dim httpClient 
As Http.HttpClient
    Dim Path 
As String "/UpdateFolder63/Folder1" 'مسار المجلد في الموقع 
في بداية اقلاع النموذج
PHP كود :
       'تعريفات و ضبط اعدادت
        httpClient = New Http.HttpClient(New Http.WebRequestHandler With {
                                             .ReadWriteTimeout = 10 * 1000}) With {.Timeout = TimeSpan.FromMinutes(20)}


        config = New DropboxClientConfig("AnyThing") With {.HttpClient = httpClient}

        client = New DropboxClient(My.Settings.AccessToken, config) 
لقد خزنا Access Token داخل اعدادات البرنامج لنستدعيها في اي مكان.

يتبع ....
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد
تم الشكر بواسطة: asemshahen5
#2
الان سنقوم بمعالجة عملية الرفع وفق التالي.
سنحدد الملفات التي نريد رفعها عبر CheckBox و من ثم نقوم بالمرور على كل صفوف الجدول فاذا وفق ان الصف محدد 
سنقوم عندها برفع الملف .
PHP كود :
   Private Async Sub Btn_Upload_Click(sender As ObjectAs EventArgsHandles Btn_Upload.Click

        If DGV1
.RowCount 0 Then
            For Each Row 
As DataRow In Dt_FileUpdate.Rows
                If Row IsNot Nothing Then
                    If Row
("Status").ToString "True" Then
                        Lb_FileToUpload
.Text Row("FilePath")
 
                       Btn_Upload.Enabled False
                        Await Uploader
(clientPathRow("FileName"), Row("FilePath"))
 
                       Btn_Upload.Enabled True
                    End 
If

 
               End If
 
           Next
        End 
If


 
   End Sub
End 
Class 
الدالة المسؤولة عن الرفع هي دالة من النوع Asyncronis تحتاج الى عدة وسائط (كائن DropboxClient , مسار الرفع و اسم الملف و مساره) و كلها تتوفر لدينا في الجدول و لكل ملف.

الدالة Uploader :
PHP كود :
   ''' <summary>
    ''' 
رفع ملفات
    
''' </summary>
    ''' 
<param name="dbx"></param>
 
   ''' <param name="folder"></param>
    ''' 
<param name="_file"></param>
 
   ''' <param name="fileToUpload"></param>
    ''' 
<returns></returns>
 
   Private Async Function Uploader(ByVal dbx As DropboxClientByVal folder As StringByVal _file As StringByVal fileToUpload As String) As Task
        Const ChunkSize 
As Integer 1024

        Using fileStream 
File.Open(fileToUploadFileMode.Open)

 
           If fileStream.Length <= ChunkSize Then
                Await dbx
.Files.UploadAsync(folder "/" _fileWriteMode.Overwrite.Instancebody:=fileStream)
 
           Else
                Await UploadWthProgress
(dbxfolder "/" _filefileStreamCInt(ChunkSize))
 
           End If
 
       End Using
    End 
Function


 
   ''' <summary>
    ''' 
الرفع مع بروجرس
    
''' </summary>
    ''' 
<param name="dbx"></param>
 
   ''' <param name="path"></param>
    ''' 
<param name="stream"></param>
 
   ''' <param name="chunkSize"></param>
    ''' 
<returns></returns>
 
   Private Async Function UploadWthProgress(ByVal dbx As DropboxClientByVal path As StringByVal stream As FileStreamByVal chunkSize As Integer) As Task
        Dim numChunks 
As ULong CULng(Math.Ceiling(CDbl(stream.Length) / chunkSize))
 
       Dim buffer As Byte() = New Byte(chunkSize 1) {}
 
       Dim sessionId As String Nothing

        Dim idx 
As ULong 0
        PG2
.Invoke(New Action(Sub()
 
                                 idx 0
                                  Me
.PG2.Value 0
                                  PG2
.Maximum numChunks 1
                              End Sub
))



 
       For idx 0 To numChunks 1
            Dim byteRead 
stream.Read(buffer0chunkSize)

 
           Using memStream = New MemoryStream(buffer0byteRead)

 
               If idx 0 Then
                    Dim result 
Await dbx.Files.UploadSessionStartAsync(FalsememStream)
 
                   sessionId result.SessionId
                Else
                    Dim cursor 
= New UploadSessionCursor(sessionIdCULng(chunkSize) * idx)

 
                   If idx numChunks 1 Then
                        Lb_FileToUpload
.Invoke(New Action(Sub()
 
                                                             Lb_FileToUpload.Text "اكتمل الرفع"
 
                                                             Lb_FileToUpload.Update()
 
                                                         End Sub))

 
                       Dim fileMetadata As FileMetadata Await dbx.Files.UploadSessionFinishAsync(cursor, New CommitInfo(path), memStream)

 
                   Else
                        Await dbx
.Files.UploadSessionAppendV2Async(cursorFalsememStream)
 
                       Lb_FileToUpload.Invoke(New Action(Sub()
 
                                                             Lb_FileToUpload.Text "Uploading..." "  " path "  " numChunks " / " idx
                                                              Lb_FileToUpload
.Update()
 
                                                             Me.PG2.Value idx 1
                                                          End Sub
))

 
                   End If

 
               End If
 
           End Using
        Next
    End 
Function 

الدالة تم تقسيمها الى جزئين و السبب هو وجود ملفات ذات حجم كبير يمكن ان يتم رفعها الى المساحة و بالتالي لا بد من طريقة لاشعار المستخدم ان هناك تقدم في عملية الرفع بدل الانتظار لوقت ظويل دون معرفة ما يجري في الخلفة.
اما الملفات الصغيرة فيتم تحميلها مباشرة دون الشعور بتقدم المؤشر و يمكن التحكم باقل حجم بعده ينطلق الجزء الثاني من الدالة عبر تغير قيمة المتغير ChunkSize .
صراحة تم العمل كثيراً على هذا الجزء الخاص بربط ProgressBar مع عملية التحميل حيث ان العملية غير مدعومة داخل المكتبة .
و كون عملية الرفع تجري في الخلفية في Task منفصل فكان من الصعب جداً الوصول الى طريقة فعالة , و لكن و الحمد لله تم حل المشكلة و هي تعمل بكفاءة.


-------------------------------------------------------------
الشق الثاني المتعلق بتحميل الملفات : يجري بنفس السيناريو حيث نقوم بتحميل اسماء الملفات ضمن المسار المحدد الى ListBox و من ثم نقوم بالمرور على الملفات داخل المسار و نحملها تباعاً الى مسار محدد ستراه داخل الكود.
اجراء التحميل:
PHP كود :
   Private Async Sub Btn_Download_Click(sender As ObjectAs EventArgsHandles Btn_Download.Click

        Dim 
list = Await ListFolder(clientPath)
 
       GroupBox4.Text "Files To Download in Folder : " Path

        Try
            For Each Itm In 
list.Entries

                If Itm
.IsFile Then
                    Btn_Download
.Enabled False
                    Await Downloader
(clientPathItm.AsFile)
 
                   Btn_Download.Enabled True
                End 
If

 
           Next
            Label1
.Text "اكتمل التحميل..."
 
       Catch ex As Exception

        End 
Try

 
   End Sub 
الدالة ListFolder داخل الكود مهمتها مزدوجة تقوم بالمرور على شقين داخل المسار المحدد.
الشق الاول تقوم بجلب كل المجلدات الفرعية داخل المسار , اهذا انا انشأت مجلدات فرعية في بداية الشرح..
الشق الثاني تقوم بجلب كل الملفات داخل المسار المحدد (داخل المجلد المحدد في المسار).
شكل الدالة :
PHP كود :
   ''' <summary>
    ''' 
جلب الملفات من مسار محدد ضمن الموقع
    
'''DropBox المسار هو مجلد داخل 
    ''' 
</summary>
 
   ''' <param name="client"></param>
    ''' 
<param name="path"></param>
 
   ''' <returns></returns>
    Private Async Function ListFolder(ByVal client As DropboxClient, ByVal path As String) As Task(Of ListFolderResult)

        Dim list = Await client.Files.ListFolderAsync(path)
        '
هذا لجلب مجلدات ضمن المسار
        
'For Each item In list.Entries.Where(Function(i) i.IsFolder)
        ' 
   ListBox_Folders.Items.Add(item.Name)
 
       'Next


        ListBox_Files.Items.Clear()
        '
جلب املفات ضمن المسار
        For Each item In 
list.Entries.Where(Function(ii.IsFile)
 
           Dim file item.AsFile
            ListBox_Files
.Items.Add(file.Size " / " item.Name)
 
       Next


        Return 
list
 
   End Function 
اما دالة التحميل  Downloader فهي تقوم بتحميل الملف بدلالة مساره و اسمه القادم من الموقع الى مكان محدد داخل جهازي 
وهو هنا (D:\Test Folder\) يمكنك جعل الامر اكثر تفاعلا بجعل المستخدم يحدد المكان.

شكل الدالة :
PHP كود :
   ''' <summary>
    ''' 
تحميل ملفات تم الدمج وفق طريقتين
    
''' </summary>
    ''' 
<param name="client"></param>
 
   ''' <param name="folder"></param>
    ''' 
<param name="file"></param>
 
   ''' <returns></returns>
    Private Async Function Downloader(ByVal client As DropboxClient, ByVal folder As String, ByVal file As FileMetadata) As Task

        Using response = Await client.Files.DownloadAsync(folder & "/" & file.Name)
            Dim fileSize As ULong = response.Response.Size
            Const bufferSize As Integer = 1024 * 1024
            Dim buffer = New Byte(bufferSize) {}

            Using stream = Await response.GetContentAsStreamAsync()
                Using file2 = New FileStream("D:\Test Folder\" & file.Name, FileMode.OpenOrCreate)
                    Dim length = stream.Read(buffer, 0, bufferSize)
                    While (length > 0)
                        file2.Write(buffer, 0, length)
                        Dim percentage = 100 * CType(file2.Length, ULong) / fileSize
                        Label1.Invoke(New Action(Sub()
                                                     Label1.Text = "Download" & "  " & file.Name & " " & fileSize & " / " & CInt(percentage)
                                                     Label1.Update()
                                                     Me.PG.Value = percentage

                                                 End Sub))


                        length = stream.Read(buffer, 0, bufferSize)

                    End While
                End Using
            End Using

        End Using

    End Function 
الى هنا نكون قد وصلنا الى الهدف من برنامجنا.
المكتبة تمكنك من عمل الكثير من انشاء مجلدات و ملفات و التعديل عليها و الحذف و غيرها من الامور الاعتيادية التي تستطيع التعامل معها , ان كان على مستوى خاص او على مستوى فريق .... الخ
نحن اكتفينا ببعض الامور التي تفيدنا .

الملف المرفق يحتوي على المثال كامل .
ان كنت ستعتمد عليه , فعليك بتغير Access Token الى الخاص بك في اعدادات البرنامج.


صور للاستخدام.












دمتم بخير و الله الموفق.


الملفات المرفقة
.rar   DropBoxManager.rar (الحجم : 1.3 م ب / التحميلات : 24)
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد
#3
السّلام عليكم و رحمة الله و بركاته
بارك الله فيك و لك و جزاك خير الجزاء إن شاء الله
موضوع بكل صدق جد مميّز .. تميّز شخصك الكريم
تحياتي و تقييماتي
الرد
تم الشكر بواسطة: asemshahen5 , ابو ليلى
#4
دائما سباق في المواضيع التي لايسلط الضوء عليها
ودائما مميز في مواضيعك ومقالاتك الرائعه
الرد
تم الشكر بواسطة: asemshahen5 , ابو ليلى


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  تفعيل برنامج Visual Studio 2019 Adilo idabdellah 4 2,913 20-05-20, 11:48 AM
آخر رد: الفاضي
  برنامج المبيعات والمشتريات والمخازن و المطاعم mgr21002100 2 235 07-04-20, 04:29 AM
آخر رد: mgr21002100
Lightbulb [مقال] التعامل مع ملفات اوفيس من خلال مكتبة NPOI ابو ليلى 1 591 05-12-19, 04:32 PM
آخر رد: sofiane-phy
  شرح انشاء برنامج دردشة بسيط CLARO 1 1,903 25-08-19, 04:30 AM
آخر رد: أمجد وضاح
  [VB.NET] برنامج ستايلات للفيجوال بيسك DK-x 2 1,885 14-08-19, 07:51 PM
آخر رد: أمجد وضاح
  [مقال] دوال التعامل مع النصوص Strings - VB.NET ابو ليلى 10 10,886 15-04-19, 07:09 PM
آخر رد: alsouf
  العلاقات بين الجداول-الاضافة و الحذف و التعديل-برنامج لحفظ مصادر الموقع ابو ليلى 13 8,440 04-04-19, 10:08 PM
آخر رد: اباذر
Information تحميل برنامج الفيجوال بيسك 2010 download visual basic 2010 mohamed atef2018 4 51,676 15-03-19, 07:50 PM
آخر رد: العتيق
  حمل برنامج رائع بخصوص تصميم أي تخطيط إنسيابي للمشاريع Flowchart عبدالله خضر 2 2,869 10-02-19, 04:35 PM
آخر رد: ahmed_gh
  [VB.NET] عمل برنامج تشفير بخوارزمية base64 alking-0999 2 2,802 31-01-19, 07:28 PM
آخر رد: khalil7547

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم