chrome扩展在popup、background、content之间通信解决传输文件问题

文章目录

背景介绍

示例扩展API版本MV2。

以弹出窗口(popup)和背景页面(background page)为例。

在浏览器中,弹出窗口(popup)和背景页面(background page)之间可以通过消息通道进行通信。但是,由于安全限制 ,弹出窗口不能直接访问背景页面的文件系统或进行文件传输。

然而,可以使用一些方法来实现弹出窗口向背景页面传输文件,就是在popup页面将文件转为base64的字符串格式向background传输,然后再将base64重新转为file对象,达到传输文件的目的。

案例介绍

从popup页面选择文件开始上传,触发上传按钮后,获取到选择的文件并将文件传输到background,触发上传接口传输到服务器端,完成文件上传操作。

代码示例

使用到的js工具有,jquery、axios。

popup页面,上传文件页面

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>popup</title>
    <style>
        body {
            width: 400px;
            height: 450px;
            background-color: aliceblue;
        }
        .contnet {
            display: flex;
            flex-direction: column;
            flex-wrap: nowrap;
            align-items: center;
        }
        .upload_file {
            display: flex;
            flex-direction: column;
            margin-top: 88px;
        }
        .upload_btn {
            border: none;
            border-radius: 10px;
            background-color: #4343e0;
            font-size: 16px;
            color: white;
            font-weight: 400;
            font-family: '微软雅黑';
            cursor: pointer;
        }
        .upload_btn:hover {
            border: none;
            border-radius: 10px;
            background-color: #4343e0;
            font-size: 16px;
            color: white;
            font-weight: 400;
            font-family: '微软雅黑';
            cursor: pointer;
            box-shadow: 0px 0px 0px 1px #848181;
        }
    </style>
</head>
<body>
    <div class="contnet">
        <div class="upload_file">
            <!--  
              type: input类型为文件选择类型
          		name: 参数名
              accept: 上传文件的可选类型
          	-->
            <input id="uploadFile" type="file" name="myFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet|application/vnd.ms-excel" style="margin-bottom: 5px;" />
            <button id="uploadFileBtn" class="upload_btn" type="button">上传</button>
        </div>
    </div>
</body>
<script type="text/javascript" src="/utils/chrome.js"></script>
<script type="text/javascript" src="/lib/jquery-3.6.3.js"></script>
<script type="text/javascript" src="/popup/popup.js"></script>

</html>

popup页面,js上传代码,file文件转base64

javascript 复制代码
// popop.js、jquery-3.6.3.js
// 绑定文件上传的button
$("#uploadFileBtn").click(() => {
    // 如果是单文件上传,选择第一个文件上传
    //let file = $("#uploadFile")[0].files[0] // ok
    let file = $("#uploadFile").prop('files')[0]
    if (!file) {
        alert('文件上传:' + '请先选择文件')
        return
    }
    let boo = confirm('是否确认上传文件?\n\r 请谨慎操作上传文件')
    if (boo) {
        // file转base64
        let reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = () => {
            let base64 = reader.result.split(',')[1]
            // 发送base64到background
            // chrome.js
            sendMessageToBackground({type: 'upload', base64: base64}, (rsp) => {
                // 上传成功 or 失败后做一些操作
            })
        }
    }
})

background监听消息,base64转file文件,axios上传

javascript 复制代码
// 上传文件
// axios.js
// base64: popup传过来的数据
function uploadFile(base64) {
    // base64转blob
    let blob = base64ToBlob(base64, 'application/vnd.ms-excel')
    // blob转file
  	let file = new File([blob], '上传文件的名字[filename].xlsx', {type: 'application/vnd.ms-excel'})

    // 构造formData表单对象,发起post请求
    let formatData = new FormData()
    formatData.append('file', file)
  
  	// axios发送文件上传的请求
    return axios({
        url: 'upload_url',
        method: 'POST',
        headers: {
            'xx-header': 'xxx',
            // 'Content-Type': 'multipart/form-data' // 不需要设置Content-Type请求头,axios请求机制会自动判断,发起什么样的请求
        },
        transformRequest: [(data, headers) => {
            delete headers['Content-Type']
            return data
        }],
        data: formatData
    }).then(rsp => {
        // 服务器数据响应
        return rsp.data
    })
}

/**
 *	
 * @param {*} mineType 选择适当的类型来转换base64,并创建Blob二进制对象
 *  'application/pdf': 表示 PDF 文件类型,可以以可移植文档格式查看和编辑。
 *  'application/msword' 或 'application/vnd.ms-word': 表示 Word 文档类型,可以以 Microsoft Word 格式查看和编辑。
 *  'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 表示 Word 2007 或更高版本的文件类型,可以以 Office Open XML 格式查看和编辑。
 *  'application/epub+zip': 表示 ePub 电子书类型,可以以电子书格式查看和编辑。
 *  'application/vnd.ms-powerpoint' 或 'application/mspowerpoint': 表示 PowerPoint 演示文稿类型,可以以 Microsoft PowerPoint 格式查看和编辑。
 *  'application/vnd.openxmlformats-officedocument.presentationml.presentation': 表示 PowerPoint 2007 或更高版本的文件类型,可以以 Office Open XML 格式查看和编辑。
 *  'application/vnd.ms-excel' 或 'application/msexcel': 表示 Excel 电子表格类型,可以以 Microsoft Excel 格式查看和编辑。
 *  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 表示 Excel 2007 或更高版本的文件类型,可以以 Office Open XML 格式查看和编辑。
 *  'image/jpeg'、'image/png'、'image/gif' 等:表示图像类型的数据,可以以图像的形式查看和编辑。
 * @returns 
 */
function base64ToBlob(base64, mineType) {
    mineType = mineType || 'application/octet-stream'
    const byteCharacters = atob(base64)
    const byteNumbers = new Array(byteCharacters.length)
    for(let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i)
    }
    let byteArray = new Uint8Array(byteNumbers)
    return new Blob([byteArray], {type: mineType})
}

附-转base64后直接下载

javascript 复制代码
function download(base64, mineType) {
  mineType = mineType || 'application/octet-stream'
  const dataUrl = `data:${mineType};base64,${base64}`

  const link = document.createElement('a')
  // document.body.appendChild(link)
  link.href = dataUrl
  link.download = 'file.xlsx' // 前提需要先知道是什么文件类型
  link.click() // 点击下载
  // document.body.removeChild(link) // 下载完成后移除标签
}
相关推荐
y先森2 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy2 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189112 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz5 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇5 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒5 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员5 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐5 小时前
前端图像处理(一)
前端