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) // 下载完成后移除标签
}
相关推荐
栈老师不回家2 分钟前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙8 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠12 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds32 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
bysking3 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓3 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4113 小时前
无网络安装ionic和运行
前端·npm