اظهار تقدم تحميل الملفات

السلام عليكم، مرحباً جميعاً

ماذا لو اردت عرض شريط تقدم تحميل الملفات للمستخدم( لدي form تحتوي على فيديو ربما يصل حجمه لاكثر من ٢٠ ميجا بايت )
و اريد عرض التقدم للمستخدم كي لا يشعر بالملل او ليعرف ان الرفع جار الان…

الاسألة التي تأتيني من سوف أسأل عن حالة االتقدم ؟

  • السيرفر
    -استضافة الملفات aws s3

السناريو الذي خطر في البال:
ان اقوم بإنشاء method تعيد قيمة التحميل ك json واقوم بالاتصال بها عبر js

يعني عند الضغط على زر submit ال form تعمل بشكل اعتيادي ويتم تنفيذ method في js تخاطب السيرفر وتجلب قيمة التحميل وتطبعها للمستخدم (لا تهمني اكواد التصميم يهمني جلب حالة التقدم)

في المقابل على السيرفر كيف ساتحقق من التقدم من form request وحالتها
هل هناك طريقة للسؤال عن حالة request من خلال رمز او id خاص بها ؟ لجلبها وقياس تقدمها

ام هناك طرق افضل وهذه الطريقة بصراحة لم اجربها فقط اريد السؤال هل ستعمل ام لا :smile: او اذا حدى اشتغل ع نفس الفكرة قبل

4 Likes

وعليكم السلام سامر،

كل الذي يلزمك من طرف الباك اند هو الـ File Upload Parser والعمليات الحسابية وكل شي راح يتم في الفرونت من خلال الـ JS

لو تطلع على الـ DOCS في MDN الخاصة بالـ Ajax

راح تلاقي انه عندك addEventListener للتالي

الإيفنت progress:
من خلالة راح تحدث الـ Update Progress

الإيفنت load:
من خلالة راح نحدد إنتهاء عملية الرفع transfer Complete

الإيفنت error:
راح نتعامل من خلالة مع المشاكل الي راح تظهر اثناء الرفع transfer Failed

الإيفنت abort:
راح تتعامل مع عملية الكنسلة transfer Canceled

oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);

التالي مثال لعملية حساب الـ Progress :

<script>
function uploadFile(){

// get the file element then select file[0]
var file = file.files[0];

//append file to formdata
var formdata = new FormData();
formdata.append("file", file);

var oReq = new XMLHttpRequest();

oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);

oReq.open("POST", "fileUploadParser path");
oReq.send(formdata);

}

function updateProgress(event){
    //Calculate the percent
    var percent = (event.loaded / event.total) * 100;

    //update the value of the html5 progress bar 
    element.value = Math.round(percent);
}

function transferComplete(event){
      //update the value of the html5 progress bar to 0
    element.value =  0;
}
 
//Handel error 
function transferFailed(event){}

//Handel abort
function transferCanceled(event){}

</script>

2 Likes

هذا المتغيير يأخذ قيمة form من html ؟؟

وهذا يقرا الملف من الحقل ؟

بالنسبة للطلب post الى اين ستكون وجهته لنفس رابط الفورم على السيرفر ؟؟
path = ???

2 Likes

var formdata = new FormData();

هذا المتغير نستخدمه لعمل FormData علشان نعمل append للملف في الـ request

وهذا يقرا الملف من الحقل ؟

هذا ما اقصدة: راح يكون عندك حقل الرفع مثلاً بالـ HTML

<input id="file" type="file" name="file">

وبعدين بالـ JS راح تجلب الملف الذي تم رفعه هكذا

$( "#upload" ).on('click', function() {
      
      let  file = $( "#file" ).files[0];

    });
2 Likes

قصذت هنا هل هذه ميثود مختلفة عن حفظ نفس المنتج ؟


def UploadedImageConfigPath(instance, filename):
	return os.path.join("video", str(instance.author), str(instance.level), "image", filename)


class AccountGame(models.Model):
	game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name='account_game'))
	video = models.FileField(upload_to=UploadedVideoConfigPath)

طبعا url اضافة هذا العنصر /add-account
هل بنفس المسار سأتصل على نفس ال view ؟

ام اعمل method اخرى فقط لرفع للملف ؟

2 Likes

هل الفكرة بالمجمل ليست لها علاقة بالفورم يعني اقوم باضافة الملف لل طلب ثم اقوم بارساله هنا

وهو بطبيعة الحال يرفع ويقيس التقدم صحيح فهم المسألة ؟
بهذه الحالة الا اكون قد رفعت الملف مرتين ؟؟
مرة من js ومرة من django form ؟
كيف سيتعامل السيرفر مع هذا الامر ؟

2 Likes

قصذت هنا هل هذه ميثود مختلفة عن حفظ نفس المنتج ؟

لا، مش لازم يكون ميثود منفصلة طالما بتتعامل مع الفورم

2 Likes

إطلع على هذه المقالة قد تفيدك في موضوع رفع الملفات بالجانقو

كذلك تأكد من ان اسم الفيديو Unique

1 Like

بتتعامل مع الـ templates ما بيحتاج لك الـ FormData هذا في حالة ارسلت الريكويست ل Endpoint و API

1 Like

صحيح المشروع كامل يعتمد على templates وليس api

2 Likes

هل الفكرة بالمجمل ليست لها علاقة بالفورم يعني اقوم باضافة الملف لل طلب ثم اقوم بارساله هنا
وهو بطبيعة الحال يرفع ويقيس التقدم صحيح فهم المسألة ؟

نعم انت فقط ترفع الملف بطريقة عادية وتقوم بقياس التقدم بالـ Ajax

كيف سيتعامل السيرفر مع هذا الامر ؟

السيرفر ماراح يتغير فيه شيء راح يتعامل مع الموضوع كان مافي عندك Progress

2 Likes

قرأت المقال تقريبا اعرف كل محتواه شكرا :wink:

سأجرب الامر بهذه الطريقة

2 Likes

اذا احتجت شيء موجودين

2 Likes

:blush: شكرااااااااااً

2 Likes

my upload js

$(document).ready(function() {

	$('form').on('submit', function(event) {

		event.preventDefault();



//append file to formdata

		var formData = new FormData($('form')[0]);
		//var input_video = $('#id_video');
		//var file = input_video[0].files[0];
		//formData.append("file", file);

		$.ajax({
			xhr : function() {
				var xhr = new XMLHttpRequest();

				xhr.upload.addEventListener('progress', function(e) {

					

					console.log('Bytes Loaded: ' + e.loaded);
					console.log('Total Size: ' + e.total);
					console.log('Percentage Uploaded: ' + (e.loaded / e.total));


					var percent = Math.round((e.loaded / e.total) * 100);

					$('#progressBar').attr('aria-valuenow', percent).css('width', percent + '%').text(percent + '%');


				});

				return xhr;
			},
			type : 'POST',
			url : '/add-account/',
			data : formData,
			processData : false,
			contentType : false,

			success : function(data) {
				var url = window.location.href.replace('/add-account/', '/account-detail/') + data.account_id;
				window.location.assign(url);

			}
		});

	});

});

وقمت بتعديل ال view لتقوم بارجاع id العنصر الجديد لاعادة توجيهه لصفحة تفاصيل العنصر بعد الرفع ولكن من نفس js

			data = {
        		'account_id': account.pk,
    		}
			#return redirect('account_detail', account_id=account.id)
			return JsonResponse(data)

كما تلاحظ كان الارجاع عبارة عن اعادة توجيه لصفحة account_detail

الان التوجيه اصبح من js بهذا الشكل:

			success : function(data) {
				var url = window.location.href.replace('/add-account/', '/account-detail/') + data.account_id;
				window.location.assign(url);

			}

لكن المشكلة الرئيسية لم تحل بعد

في ال console
اول قيمة تتم طباعتها هي تم التحميل ١٠٠٪

لاحظ الحجم الخاص بالفورم تقريبا كحجم الفيديو واكثر بكم بايت
الامر الاخر ان ميثود التحقق يتم تنفيذها بعد مرور ١٠-١٥ ثانية يعني التحميل ينجح عن طريق ajax ويتم تحويلي لصفحة التفاصيل
لكن من اول مرة يتم طباعة قيمته كاملة وتتم طباعته مرة واحدة اليس المفروض progress يعمل بشكل مستمر

2 Likes

هههههههههههههههههههههههه كنت خايف من شيء وفعلا كما توقعت الموضوع يتعلق بالسيرفر المحلي
عادةً عندما ارفع ملف بحجم ٢٠ ميجا بايت يستغرق مني اجزاء من الثانية
بينما على الاستضافة يستغرق ٢٠ ثانية ! :smile:
جربت على الاستضافة يعمل بشكل ممتاز

بالتأكيد سأقوم بتغيير الكود ليتناسب مع الاخطاء وحالات الفشل
شكرا جدا لاهتمامكم .

2 Likes

:joy::joy:

جميل جداً :ok_hand:

2 Likes