123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package main
- import (
- "net/url"
- "os"
- "path/filepath"
- "strings"
- "unsafe"
- "github.com/energye/energy/v2/cef"
- )
- func RegSchema(browser *cef.ICefBrowser) {
- // 创建 SchemeHandlerFactory
- factory := cef.SchemeHandlerFactoryRef.New()
- // 创建SchemeHandlerFactory的回调函数
- factory.SetNew(func(browser *cef.ICefBrowser, frame *cef.ICefFrame, schemeName string, request *cef.ICefRequest) *cef.ICefResourceHandler {
- handler := cef.ResourceHandlerRef.New(browser, frame, schemeName, request)
- var (
- // 预设一些变量
- fileBytes []byte
- fileBytesReadPosition = 0
- err error
- status int32 = 0
- statusText = ""
- mimeType = ""
- )
- // 当加载指定的 scheme 后, 回调以下函数, 按step
- // step 1, ProcessRequest , 处理请求, 在这里预先加载需要的资源和 step 2 需要的响应状态
- handler.ProcessRequest(func(request *cef.ICefRequest, callback *cef.ICefCallback) bool {
- urlFile := request.URL()
- // 默认404
- status = 404
- statusText = "ERROR"
- mimeType = ""
- // 请求地址是我们预告定义好的地址
- i := strings.Index(urlFile, "file")
- if i == 0 {
- fpath := strings.TrimLeft(urlFile, "file:///")
- fpath, err = url.QueryUnescape(fpath)
- if err != nil {
- fileBytes = nil
- return false
- }
- fpath = strings.Split(fpath, "?")[0]
- fileBytes, err = os.ReadFile(fpath)
- if err != nil {
- println("ProcessRequest url:", fpath, err.Error())
- fileBytes = nil
- return false
- }
- println("ProcessRequest url ok:", fpath)
- fileBytesReadPosition = 0 //每次都将读取位置归0
- // 加载资源成功后设置成功响应状态
- status = 200
- statusText = "OK"
- ext := strings.TrimLeft(filepath.Ext(fpath), ".")
- mimeType = cef.GetMimeType(ext) // get html MimeType
- callback.Cont() // 继续
- return true
- } else {
- // 返回 false 后不会执行 ReadResponse 回调函数
- fileBytes = nil
- return false
- }
- })
- // step 2, 响应处理器, 将 step 1 的处理结果返回
- handler.GetResponseHeaders(func(response *cef.ICefResponse) (responseLength int64, redirectUrl string) {
- if fileBytes != nil {
- response.SetStatus(status)
- response.SetStatusText(statusText)
- response.SetMimeType(mimeType)
- responseLength = int64(len(fileBytes))
- }
- return
- })
- // step3, 读取响应内容
- handler.ReadResponse(func(dataOut uintptr, bytesToRead int32, callback *cef.ICefCallback) (bytesRead int32, result bool) {
- // 这个函数可能会被多次调用, 如果响应流大于 bytesToRead 时
- // 我们是按块读取 每个块最大bytesToRead且小于实际的要响应的流字节数
- // 从最新的读取位置fileBytesReadPosition把流返回到 dataOut
- if fileBytes != nil && len(fileBytes) > 0 {
- var i int32 = 0 // 默认 0
- // 循环读取字节流内容
- for i < bytesToRead && fileBytesReadPosition < len(fileBytes) {
- // 这里是通过指针地址将赋值, []byte 缓存数组
- // 描述: dataOut byte[i] = fileBytes byte[fileBytesReadPosition]
- *(*byte)(unsafe.Pointer(dataOut + uintptr(i))) = fileBytes[fileBytesReadPosition]
- fileBytesReadPosition++ // 缓存数据的下一个位置, 如果 len(fileBytes) 大于 bytesToRead 时
- i++ // 计数, 当前最后的输出大小
- }
- // i当前读取的字节数
- return i, i > 0
- }
- return
- })
- return handler
- })
- requestContext := browser.GetRequestContext()
- requestContext.RegisterSchemeHandlerFactory("file", "", factory)
- }
|