例如,我想将 https://www.sunzhongwei.com 网页中下载到的 Excel 文件,上传到其他服务器。这里以 http://localhost:5000 为本地测试环境。
tampermonkey 中是否可以使用 fetch / jQuery ajax
还是必须使用 GM_xmlhttpRequest ?
测试了一下,用 fetch 确实不行,必须使用 GM_xmlhttpRequest 。
以下是使用 fetch 的报错信息,估计使用 jquery ajax 也是同样的结果。
Access to fetch at 'http://localhost:5000/' from origin 'https://www.sunzhongwei.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
POST http://localhost:5000/ net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
如果是同一个域名,就可以使用 fetch 了。
官方文档对 GM_xmlhttpRequest 的说明
https://wiki.greasespot.net/GM.xmlHttpRequest
This method performs a similar function to the standard XMLHttpRequest object, but allows these requests to cross the same origin policy boundaries.
也就是说使用这个函数才能绕过 cross the same origin policy 的限制。
URL is not a part of the @connect list
在向本地服务 http://localhost:5000 提交数据时,报错:
URL is not a part of the @connect list
看起来是没有添加域名白名单。注意,不需要加端口号,如果加了端口号,同样会报这个错误。
正确的设置如下:
// @connect localhost
指定 Excel 文件的下载格式
GM_xmlhttpRequest 的相关参数:
- 请求参数 responseType: one of arraybuffer, blob, json
- 返回值 response: the response data as object if details.responseType was set
arraybuffer 与 blob 的区别
Blob,是英文 Binary Large Object (二进制大型对象)的缩写。
Blob 对象表示一个二进制文件的数据内容,通常用来读写文件,比如一个图片文件的内容就可以通过 Blob 对象读写。 所以下载的 Excel 文件,就需要用 Blob 格式来存储。到上传的时候,再原封不动地传到新的服务器上。
与 ArrayBuffer 区别:
- Blob 用于操作二进制文件
- ArrayBuffer 用于操作内存。没太看懂,感觉是以数组的形式打印二进制流。
Blob 上传
GM_xmlhttpRequest 的 binary 参数,支持数据二进制模式。
binary send the data string in binary mode
参考:
https://www.tampermonkey.net/documentation.php#GM_getResourceText
这里的 binary 是用来设置参数 data 的类型,所以只能设置为 true / false。
可行的 js 代码
GM_xmlhttpRequest ( {
method: "POST",
url: "https://www.sunzhongwei.com/some-excel",
data: data,
responseType: "blob", // 获取 response 为 blob 类型
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
onload: function (response) {
console.log ("got response");
GM_xmlhttpRequest ( {
method: "POST",
url: "http://localhost:5000",
data: response.response,
binary: true, // 设置 data 以二进制形式上传
headers: {},
onload: function (response) {
console.log (response.responseText);
}
});
}
});
Python 如何获取传递来的二进制数据
以 flask 为例:
# env FLASK_APP=server.py flask run
from flask import Flask, escape, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def hello():
data = request.get_data()
with open("/mnt/d/test_a.xls", "wb") as f:
f.write(data)
return "OK"
打开文件,果然是原始的 Excel。测试成功。
Java 如何获取传递来的二进制数据
参考 tampermonkey 上传 Blob 文件到其他服务器,multipart/form-data 版 里的实现。
感悟
读官方文档,很多时候就能理出实现思路,比 Google 结果还靠谱。
参考
- https://stackoverflow.com/questions/19393744/use-gm-xmlhttprequest-to-post-data-on-chrome
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式