浏览器 indexedb 保存文件如何导出到本地

浏览器 indexedb 保存文件如何导出到本地

背景:

Webassembly 可以把文件保存到indexed,而把文件导出到本地预览,或者可视化的查看文件内容,极其不方便, 本文就介绍我的具体实现方式

思路

我的想法是把文件通过网络发送的本机的一个服务器,然后服务器接收文件流,最后写成一个文件,保存在本地,在本地进行预览

实现过程

本来想用c网络编程里边的 socket,写了demo发现不行,后来查阅资料说的需要用websocket,下边就是具体相关代码

 初始化WebSocket

JavaScript
const socket = new WebSocket('ws://localhost:40001/ws_echo');

    // Connection opened
    socket.addEventListener('open', (event) => {
        socket.send('Hello Server!');
    });

    // Listen for messages
    socket.addEventListener('message', (event) => {
        console.log('Message from server ', event.data);
    });

发送文件

JavaScript
function updateLoad()
{
    console.log("update load file");
    let path = allocateUTF8("output.mp4")
    let buf_addr = Module._readFile(path);
    let size = Module._getFileSize();
    var u8o = new Uint8ClampedArray(Module.HEAPU8.subarray(buf_addr,
    buf_addr + size));
    socket.send(u8o);
    socket.send("OK");
}

可以看到有两个webassembly的方法_readFile和_getFileSize(),

JavaScript
MDWord g_dwFileSize = 0;
MByte *g_pFileData = 0;
int EMSCRIPTEN_KEEPALIVE getFileSize()
{
    return g_dwFileSize;
}
uint8_t* EMSCRIPTEN_KEEPALIVE readFile(const char *pFileName) {
    std::string filePath = std::move(std::string("/data/") + pFileName);
    QLOGE("readFile filePath=%s\n", filePath.c_str());

    MDWord dwSize = MStreamFileGetSize(filePath.c_str());
        QLOGE("readFile dwSize = %d\n", dwSize);

    if (dwSize != g_dwFileSize)
    {
        if (g_pFileData != MNull)
        {
            MMemFree(MNull, g_pFileData);
        }
    }
    g_pFileData = (MByte *)MMemAlloc(MNull, dwSize);
    g_dwFileSize = dwSize;
    FILE* fp = fopen(filePath.c_str(), "rb");
    if (fp != MNull )
    {
        char buf[1024] ={0};
        int size = 0;
        dwSize = 0;
        while((size = fread(buf,1,sizeof(buf),fp)) > 0)
        {
            MMemCpy(g_pFileData + dwSize, buf, size);
            dwSize += size;

        }
        fclose(fp);
    }   
    return g_pFileData;
}

很简单的客户端

接收文件

接收文件需要在本地构建一个服务器,这里我们采用go语言实现了一个简单服务器,具体代码如下:

Go
package main

import (
    "fmt"
    "log"
    "net/http"
    "syscall"

    "golang.org/x/net/websocket"

    "os"
    "os/signal"
)

func main() {
    log.Println("ws_echo start...")

    wsPort := 40001
    go func() {
        log.Println(fmt.Sprint("WebSocket:", wsPort, " Listening ..."))
        http.Handle("/ws_echo", websocket.Handler(webSocketHandler))
        err := http.ListenAndServe(fmt.Sprint(":", wsPort), nil)
        if err != nil {
            panic("ListenAndServe: " + err.Error())
        }
    }()

    httpPort := 80
    go func() {
        log.Println(fmt.Sprint("http:", httpPort, " Listening ..."))
        err := http.ListenAndServe(fmt.Sprint(":", httpPort),
            http.FileServer(http.Dir("./")))
        if err != nil {
            panic("ListenAndServe: " + err.Error())
        }
    }()

    ch := make(chan os.Signal, 1)
    signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
    log.Printf("ws_echo quit (%v)\n", <-ch)
}

func webSocketHandler(ws *websocket.Conn) {
    ws.PayloadType = websocket.TextFrame
    defer ws.Close()

    rtemp := make([]byte, 1024*1024*50)
    file, err := os.OpenFile(
        "test.bin",
        os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
        0666,
    )
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    ws.Read(rtemp)

    for {
        n, err := ws.Read(rtemp)
        if err != nil {
            log.Println("Error:Read:", err)
            return
        }
        // myString := string(rtemp)
        log.Println("size:", n)

        // log.Println("read:", myString)

        // n, err = ws.Write(rtemp[:n])
        if n==2 && rtemp[0]=='O' && rtemp[1]=='K'{
            log.Printf("Save Ok.\n")
            break;
        }
        // 写字节到文件中
        byteSlice := rtemp[:n]
        bytesWritten, err := file.Write(byteSlice)
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Wrote %d bytes.\n", bytesWritten)

    }
}

最终我们把接收到文件保存成了test.bin,接收成功即可在本地进行预览操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值