chunks streadming, my network models
This commit is contained in:
1 parent
a2c3fe4f98
commit
dba359bb6a
15 files changed
+625
-20
No files matched your search
@@ -0,0 +1,199 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Загрузка и стриминг файла</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
section { margin-bottom: 40px; }
|
||||
label { display: block; margin-bottom: 5px; }
|
||||
input, button { margin-bottom: 10px; }
|
||||
#log { border: 1px solid #ccc; padding: 10px; max-height: 200px; overflow-y: auto; background: #f9f9f9; }
|
||||
</style>
|
||||
<!-- Including jsSHA library from CDN -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/3.2.0/sha256.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Загрузка и стриминг файла</h1>
|
||||
|
||||
<section id="uploadSection">
|
||||
<h2>Загрузка файла</h2>
|
||||
<label for="uploadFile">Выберите файл для загрузки:</label>
|
||||
<input type="file" id="uploadFile">
|
||||
<br>
|
||||
<button id="uploadBtn">Загрузить файл</button>
|
||||
<div id="uploadResult"></div>
|
||||
</section>
|
||||
|
||||
<section id="streamSection">
|
||||
<h2>Стриминг файла</h2>
|
||||
<label for="fileHashInput">Введите file_hash:</label>
|
||||
<input type="text" id="fileHashInput" placeholder="Введите hash">
|
||||
<br>
|
||||
<button id="loadFileBtn">Загрузить файл для стриминга</button>
|
||||
<div id="mediaContainer" style="margin-top:20px;"></div>
|
||||
</section>
|
||||
|
||||
<section id="logSection">
|
||||
<h2>Лог</h2>
|
||||
<div id="log"></div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
// Base URL for endpoints
|
||||
const BASE_URL = "https://my-public-node-1.projscale.dev/api/v1.5/storage";
|
||||
|
||||
// Function to append messages to log div
|
||||
function appendLog(message) {
|
||||
const logDiv = document.getElementById('log');
|
||||
const p = document.createElement('p');
|
||||
p.textContent = message;
|
||||
logDiv.appendChild(p);
|
||||
}
|
||||
|
||||
// Function to compute SHA-256 hash of a file in hex using jsSHA library with incremental reading
|
||||
function computeSHA256(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunkSize = 2097152; // 2MB per chunk
|
||||
let offset = 0;
|
||||
const reader = new FileReader();
|
||||
const shaObj = new jsSHA("SHA-256", "ARRAYBUFFER");
|
||||
|
||||
reader.onload = function(e) {
|
||||
// Update the hash object with the current chunk data
|
||||
shaObj.update(e.target.result);
|
||||
offset += chunkSize;
|
||||
appendLog(`Processed ${Math.min(offset, file.size)} из ${file.size} байт`);
|
||||
if (offset < file.size) {
|
||||
readNextChunk();
|
||||
} else {
|
||||
try {
|
||||
const hash = shaObj.getHash("HEX");
|
||||
resolve(hash);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
reader.onerror = function(err) {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
function readNextChunk() {
|
||||
const slice = file.slice(offset, offset + chunkSize);
|
||||
reader.readAsArrayBuffer(slice);
|
||||
}
|
||||
|
||||
readNextChunk();
|
||||
});
|
||||
}
|
||||
|
||||
// Upload button event listener
|
||||
document.getElementById('uploadBtn').addEventListener('click', async () => {
|
||||
const fileInput = document.getElementById('uploadFile');
|
||||
const uploadResult = document.getElementById('uploadResult');
|
||||
uploadResult.textContent = "";
|
||||
|
||||
if (!fileInput.files || fileInput.files.length === 0) {
|
||||
uploadResult.textContent = "Пожалуйста, выберите файл.";
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileInput.files[0];
|
||||
appendLog("Starting hash computation...");
|
||||
try {
|
||||
// Compute SHA-256 hash of the file in hex format
|
||||
const hashHex = await computeSHA256(file);
|
||||
appendLog(`Computed SHA-256 hash: ${hashHex}`);
|
||||
|
||||
// Prepare the POST request with file as body and header X-Content-SHA256
|
||||
const response = await fetch(BASE_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-Content-SHA256": hashHex,
|
||||
"X-File-Name": file.name, // NEW: передаём имя файла
|
||||
"Content-Type": file.type || "application/octet-stream"
|
||||
},
|
||||
body: file
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
uploadResult.textContent = `Ошибка: ${errorData.error}`;
|
||||
appendLog(`Upload failed: ${errorData.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const resultData = await response.json();
|
||||
uploadResult.textContent = `Файл загружен успешно. content_sha256: ${resultData.content_sha256}`;
|
||||
appendLog(`Upload successful. Response: ${JSON.stringify(resultData)}`);
|
||||
} catch (err) {
|
||||
uploadResult.textContent = "Ошибка при загрузке файла.";
|
||||
appendLog(`Error during upload: ${err}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Load file button event listener for streaming
|
||||
document.getElementById('loadFileBtn').addEventListener('click', async () => {
|
||||
const fileHash = document.getElementById('fileHashInput').value.trim();
|
||||
const mediaContainer = document.getElementById('mediaContainer');
|
||||
mediaContainer.innerHTML = "";
|
||||
|
||||
if (!fileHash) {
|
||||
mediaContainer.textContent = "Пожалуйста, введите file_hash.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct file URL
|
||||
const fileUrl = `${BASE_URL}/${fileHash}`;
|
||||
appendLog(`Fetching file info for hash: ${fileHash}`);
|
||||
|
||||
try {
|
||||
// Perform a HEAD request to determine Content-Type
|
||||
const headResponse = await fetch(fileUrl, { method: "HEAD" });
|
||||
if (!headResponse.ok) {
|
||||
mediaContainer.textContent = "Файл не найден.";
|
||||
appendLog("File not found during HEAD request.");
|
||||
return;
|
||||
}
|
||||
|
||||
const contentType = headResponse.headers.get("Content-Type") || "";
|
||||
appendLog(`Content-Type: ${contentType}`);
|
||||
|
||||
let mediaElement;
|
||||
// Create appropriate element based on Content-Type
|
||||
if (contentType.startsWith("image/")) {
|
||||
mediaElement = document.createElement("img");
|
||||
mediaElement.style.maxWidth = "100%";
|
||||
} else if (contentType.startsWith("video/")) {
|
||||
mediaElement = document.createElement("video");
|
||||
mediaElement.controls = true;
|
||||
mediaElement.style.maxWidth = "100%";
|
||||
} else if (contentType.startsWith("audio/")) {
|
||||
mediaElement = document.createElement("audio");
|
||||
mediaElement.controls = true;
|
||||
} else {
|
||||
// For other types, create a download link
|
||||
mediaElement = document.createElement("a");
|
||||
mediaElement.textContent = "Скачать файл";
|
||||
}
|
||||
|
||||
// Set the src or href attribute to stream the file
|
||||
if (mediaElement.tagName === "A") {
|
||||
mediaElement.href = fileUrl;
|
||||
mediaElement.download = "";
|
||||
} else {
|
||||
mediaElement.src = fileUrl;
|
||||
}
|
||||
|
||||
mediaContainer.appendChild(mediaElement);
|
||||
appendLog("Media element created and added to the page.");
|
||||
} catch (err) {
|
||||
mediaContainer.textContent = "Ошибка при загрузке файла.";
|
||||
appendLog(`Error during file streaming: ${err}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user