繁体   English   中英

如何使用 socket.io 和大于 1mb 的 nodejs 实现房间到房间的文件共享系统?

[英]How to implement room to room file sharing system using socket.io and nodejs larger than 1mb?

我想实现 socket.io 房间到房间文件共享系统,以便用户可以将图像发送到他们各自的房间,所有用户都可以看到它,我尝试使用 base64 编码方法将发送者图像文件发送到特定房间,但它只能发送大约 700kb 到800kb 文件。

Is there any easier way of doing this and can support larger files above 1mb and it should be able to load images progressively?

I am using ejs template engine, nodejs, socket.io, javascript.

Console.log("please help me guys if you any idea about this, I tried many things but none of them are working and I have read the socket.io documentation but didn't get any clue about it

我也尝试过二进制流,但没有运气请帮我一些代码示例

You will probably find it easier for the client to upload the file to your http server with a room name and then have your http server send a message to all the other clients in the room via socket.io with a URL where the client can download the file使用 http。 socket.io 不是流协议,它是基于数据包或消息的协议,因此要发送大的东西,必须将其分解为消息,然后在客户端上重新组合。 这个是可以做到的,只是http上传下载已经知道怎么做的额外的非标准工作。

以下是步骤:

  1. 客户端通过 http 帖子将文件上传到服务器,其中房间名称作为表单中的字段。
  2. 服务器接收上传的文件,为其分配一个唯一的 ID,并将其存储在服务器上磁盘上的临时位置。
  3. 当文件上传完成时,服务器通过 socket.io 通知房间中的所有其他客户端文件已上传并准备好下载,并将 URL 发送给他们以供下载,其中包含 uniqueID。
  4. 每个客户端使用他们收到的唯一 URL 通过 http 发送下载文件的请求。
  5. 服务器根据请求通过 http 将文件提供给每个客户端。
  6. 服务器要么跟踪所有客户端现在是否已完成下载,要么根据文件的时间戳在一段时间后删除文件(仅清理磁盘空间),并在循环计时器上定期清理 function。

您可以创建处理所有下载的单个路由:

const downloadRoot = "/temp/filexfer";

app.get("/download/:id", (req, res) => {
    const fullPath = path.resolve(path.join(downloadRoot, req.params.id));
    // detect any leading . or any double .. that might jump outside
    // the downloadRoot and get to other parts of the server
    if (!fullPath.startsWith(downloadRoot)) {
         console.log(`Unsafe download request ${fullPath}`);
         res.sendStatus(500);
         return;
    } 
    res.download(fullPath);
});

清理算法可能如下所示:

const fsp = require('fs').promises;
const path = require('path');
const oneHour = 1000 * 60 * 60;

// run cleanup once per hour
let cleanupTimer = setInterval(async () => {
    let oneHourOld = Date.now() - oneHour;
    try {
        let files = await fsp.readdir(downloadRoot, {withFileTypes: true});
        for (let f of files) {
             if (f.isFile()) {
                 let fullName = path.join(downloadRoot, f.name);
                 let info = await fsp.stat(fullName);
                 // if file modification time is older than one hour, remove it
                 if (info.mtimeMs <= oneHourOld) {
                     fsp.unlink(fullName).catch(err => {
                         // log error, but continue
                         console.log(`Can't remove temp download file ${fullName}`, err);
                     });
                 }
             }
        }
    } catch(e) {
        console.log(e);
    }
    
}, oneHour);

// unref the timer so it doesn't stop node.js from exiting naturally
cleanupTimer.unref();

有很多方法可以做这种事情,这在很大程度上取决于你想要支持什么样的架构。

通过 socket.io 或任何其他网络套接字发送大文件都可以。 它确实需要在您的 web 应用程序上进行大量切割和重新组装,但它会起作用。

WebRTC 是共享任何描述文件的另一种方式,它不会对您的服务器造成任何负担,这很好。 (这里有一个教程https://ably.com/tutorials/web-rtc-file-transfer

这两种方法的问题在于它们是临时共享,房间的新用户将无法获取图像,除非您的服务器再次重新传输数据。

我的建议是将文件直接上传到 s3,然后共享一个可以在每个客户端上解决的链接。 这将减轻服务器负担并减少后端服务器中的存储需求

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM