Я работаю над сервисом для загрузки больших файлов. Существует веб-интерфейс, который отправляет запрос на получение, который получает файл в виде потока. Я изучил Streamsaver.js, но мне не нужен mitm. Сейчас использую вот так
async function downloadFileFromStream(fileName, streamRef) {
// Get the stream from the .NET stream reference
const response = await streamRef.stream();
const readableStream = response.getReader();
const fileStream = streamSaver.createWriteStream(fileName);
if (window.WritableStream && readableStream.pipeTo) {
await readableStream.pipeTo(fileStream);
return;
}
const writer = fileStream.getWriter();
const pump = () => readableStream.read()
.then(({ done, value }) => {
if (done) {
writer.close();
return;
}
return writer.write(value).then(pump);
});
await pump();
}
// To register the function in the global window object so it can be called from C#
window.downloadFileFromStream = downloadFileFromStream;
Я хотел бы знать, есть ли способ, похожий на то, как я это сделал бы на С#.
псевдокод
Readstream r;
Writestream w;
r.copyToAsync(w);
яваскрипт:
window.downloadFileFromStream = async function (fileName, streamRef) {
const response = await streamRef.stream();
const reader = response.getReader();
const writableStream = new WritableStream({
async write(chunk, controller) {
await writer.write(chunk);
},
close() {
writer.close();
}
});
const writer = writableStream.getWriter();
const pump = () => reader.read().then(({ done, value }) => {
if (done) {
writer.close();
return;
}
return writer.write(value).then(pump);
});
await pump();
}
Включите этот js-файл.
@page "/download"
@inject IJSRuntime JS
<button @onclick = "DownloadFile">Download File</button>
@code {
private async Task DownloadFile()
{
var streamRef = new DotNetStreamReference(await GetFileStream());
await JS.InvokeVoidAsync("downloadFileFromStream", "example.txt", streamRef);
}
private async Task<Stream> GetFileStream()
{
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream, leaveOpen: true))
{
await writer.WriteAsync("Example file content");
}
stream.Position = 0;
return stream;
}
}
window.downloadFileFromStream = async function (fileName, streamRef) {
// Get the response from the stream reference
const response = await streamRef.stream();
const reader = response.getReader();
// Show file picker to choose save location
const handle = await window.showSaveFilePicker({
suggestedName: fileName
});
// Create a writable stream and wait for it to be ready
const writableStream = await handle.createWritable();
// Function to pump data from the reader to the writable stream
const pump = async () => {
const { done, value } = await reader.read();
if (done) {
await writableStream.close();
console.info("done");
return;
}
await writableStream.write(value);
return pump(); // Call pump again for the next chunk
};
// Start pumping data
await pump();
}
Я попробовал это и заставил его работать, если у кого-то еще есть эта проблема. Единственная проблема, которую я вижу в этом, заключается в том, что прогресс не отображается на вкладке загрузки браузера, а только в загрузке файловой системы.
это не работает. созданный вами записываемый поток не передается в папку загрузок на компьютере, он создает поток только внутри браузера.