add video upload input
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
||||||
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
||||||
import TestSection from '@/app/ui/marking-page/test-section';
|
import TestSection from '@/app/ui/marking-page/test-section';
|
||||||
import { IconVideoFile } from '@/app/ui/icons/icons';
|
import UploadSectionVideo from '@/app/ui/marking-page/upload-section-video';
|
||||||
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
@@ -10,6 +11,7 @@ export default function Page() {
|
|||||||
<h1 >Защита видео</h1>
|
<h1 >Защита видео</h1>
|
||||||
</div>
|
</div>
|
||||||
<ProtectionSummary />
|
<ProtectionSummary />
|
||||||
|
<UploadSectionVideo />
|
||||||
<TestSection />
|
<TestSection />
|
||||||
<ProtectedFilesTable />
|
<ProtectedFilesTable />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ body {
|
|||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useRef, useState, useCallback, ChangeEvent, DragEvent } from 'react';
|
import React, { useRef, useState, useCallback, ChangeEvent, DragEvent } from 'react';
|
||||||
import { IconImageFile } from '@/app/ui/icons/icons';
|
|
||||||
|
|
||||||
interface SelectedFile {
|
interface SelectedFile {
|
||||||
file: File;
|
file: File;
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useRef } from 'react';
|
||||||
|
|
||||||
|
const CHUNK_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
|
export default function UploadSectionVideo() {
|
||||||
|
const [uploading, setUploading] = useState(false);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [videoId, setVideoId] = useState<string | null>(null);
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const uploadVideoInChunks = async (file: File) => {
|
||||||
|
setUploading(true);
|
||||||
|
setProgress(0);
|
||||||
|
|
||||||
|
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
|
||||||
|
const uploadId = Date.now().toString();
|
||||||
|
|
||||||
|
let start = 0;
|
||||||
|
let chunkIndex = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (start < file.size) {
|
||||||
|
const end = Math.min(start + CHUNK_SIZE, file.size);
|
||||||
|
const chunk = file.slice(start, end);
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('video', chunk);
|
||||||
|
formData.append('uploadId', uploadId);
|
||||||
|
formData.append('chunkIndex', chunkIndex.toString());
|
||||||
|
formData.append('totalChunks', totalChunks.toString());
|
||||||
|
formData.append('fileName', file.name);
|
||||||
|
formData.append('fileType', file.type);
|
||||||
|
|
||||||
|
const response = await fetch('/api/upload-video', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Upload failed: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
const currentProgress = Math.round(((chunkIndex + 1) / totalChunks) * 100);
|
||||||
|
setProgress(currentProgress);
|
||||||
|
|
||||||
|
if (chunkIndex === totalChunks - 1) {
|
||||||
|
setVideoId(result.videoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
start = end;
|
||||||
|
chunkIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Video uploaded successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Upload error:', error);
|
||||||
|
alert('Upload failed');
|
||||||
|
} finally {
|
||||||
|
setUploading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileSelect = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
if (!file.type.startsWith('video/')) {
|
||||||
|
alert('Please select a video file');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await uploadVideoInChunks(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4 mb-1.5">
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref={fileInputRef}
|
||||||
|
accept="video/*"
|
||||||
|
onChange={handleFileSelect}
|
||||||
|
className="mb-4"
|
||||||
|
disabled={uploading}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{uploading && (
|
||||||
|
<div className="w-full bg-gray-200 rounded-full h-2.5 mb-4">
|
||||||
|
<div
|
||||||
|
className="bg-blue-600 h-2.5 rounded-full transition-all duration-300"
|
||||||
|
style={{ width: `${progress}%` }}
|
||||||
|
></div>
|
||||||
|
<p className="text-sm text-gray-600 mt-1">Uploading: {progress}%</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{videoId && (
|
||||||
|
<div className="mt-4 p-3 bg-green-100 border border-green-400 text-green-700 rounded">
|
||||||
|
<p>Video uploaded successfully!</p>
|
||||||
|
<p className="text-sm">Video ID: {videoId}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user