针对上传文件进行处理

This commit is contained in:
2023-12-25 23:44:26 +08:00
parent 4863fcb199
commit f9d84526a2
4 changed files with 8056 additions and 6183 deletions

View File

@@ -1,11 +1,13 @@
/** /**
利用chrome的fetch来避免跨域 利用chrome的fetch来避免跨域
**/ **/
import {getImageMd5} from "@/utils/image";
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type == 'api') { if (request.type == 'api') {
let headers = {}, data;
new Promise((resolve) => { new Promise((resolve) => {
let headers = {};
let data = null;
if (request.needMallId) { if (request.needMallId) {
headers.Mallid = request.mallId; headers.Mallid = request.mallId;
} }
@@ -25,29 +27,20 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
formData.append(key + `[${i}]`, subValue) formData.append(key + `[${i}]`, subValue)
}) })
} else { } else {
if (key == 'image') { if (key == "image") {
let blob = new Blob([request.data[key]], {type: 'application/png'}) //跳过image的处理
// formData.append(key, new Blob([request.data[key]], {type: 'application/png'})) } else formData.append(key, request.data[key])
formData.append(key, blob)
} else {
formData.append(key, request.data[key])
}
} }
}) })
data = formData data = formData
} }
headers.cookie = getCookie(); headers.cookie = getCookie();
Promise.resolve().then(() => fetch(request.url, { if (request.isFormData && !!request.data.image) {//针对图片上传特殊的处理办法
'headers': headers, getImageMd5(request.data.image).then(res => data.append('image', res.image.blobData)).then(resolve)
'method': 'POST', } else resolve()
'referrerPolicy': 'no-referrer', }).then(() => fetch(request.url, {
'credentials': 'include', headers, 'method': 'POST', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': data, 'mode': 'cors'
'body': data, })).then(res => res.json()).then(sendResponse);
'mode': 'cors'
})).then((res) => {
resolve(res.json());
});
}).then(sendResponse);
} else if (request.type == 'temuApi') { } else if (request.type == 'temuApi') {
new Promise((resolve) => { new Promise((resolve) => {
let headers = {}; let headers = {};
@@ -57,12 +50,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
headers['Content-Type'] = 'application/json'; headers['Content-Type'] = 'application/json';
headers.cookie = getTemuCookie(); headers.cookie = getTemuCookie();
Promise.resolve().then(() => fetch(request.url, { Promise.resolve().then(() => fetch(request.url, {
'headers': headers, 'headers': headers, 'method': 'POST', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors'
'method': 'POST',
'referrerPolicy': 'no-referrer',
'credentials': 'include',
'body': JSON.stringify(request.data),
'mode': 'cors'
})).then((res) => { })).then((res) => {
resolve(res.json()); resolve(res.json());
}).catch(() => { }).catch(() => {
@@ -75,10 +63,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
headers['Content-Type'] = 'text/html'; headers['Content-Type'] = 'text/html';
//headers.cookie = getTemuCookie(); //headers.cookie = getTemuCookie();
Promise.resolve().then(() => fetch(request.url, { Promise.resolve().then(() => fetch(request.url, {
'headers': headers, 'headers': headers, 'method': 'GET', 'referrerPolicy': 'no-referrer', //'credentials': 'include',
'method': 'GET',
'referrerPolicy': 'no-referrer',
//'credentials': 'include',
'mode': 'cors' 'mode': 'cors'
})).then((res) => { })).then((res) => {
// 创建了一个数据读取器 // 创建了一个数据读取器
@@ -87,7 +72,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const decoder = new TextDecoder(); const decoder = new TextDecoder();
let text = "" let text = ""
reader.read().then(function processText({ done, value }) { reader.read().then(function processText({done, value}) {
// Result 对象包含了两个属性: // Result 对象包含了两个属性:
// done - 当 stream 传完所有数据时则变成 true // done - 当 stream 传完所有数据时则变成 true
// value - 数据片段。当 done 为 true 时始终为 undefined // value - 数据片段。当 done 为 true 时始终为 undefined
@@ -108,11 +93,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
headers['Content-Type'] = 'text/html'; headers['Content-Type'] = 'text/html';
headers.cookie = getAliexpressCookie(); headers.cookie = getAliexpressCookie();
Promise.resolve().then(() => fetch(request.url, { Promise.resolve().then(() => fetch(request.url, {
'headers': headers, 'headers': headers, 'method': 'GET', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'mode': 'cors'
'method': 'GET',
'referrerPolicy': 'no-referrer',
'credentials': 'include',
'mode': 'cors'
})).then((res) => { })).then((res) => {
// 创建了一个数据读取器 // 创建了一个数据读取器
const reader = res.body.getReader(); const reader = res.body.getReader();
@@ -120,7 +101,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const decoder = new TextDecoder(); const decoder = new TextDecoder();
let text = "" let text = ""
reader.read().then(function processText({ done, value }) { reader.read().then(function processText({done, value}) {
// Result 对象包含了两个属性: // Result 对象包含了两个属性:
// done - 当 stream 传完所有数据时则变成 true // done - 当 stream 传完所有数据时则变成 true
// value - 数据片段。当 done 为 true 时始终为 undefined // value - 数据片段。当 done 为 true 时始终为 undefined
@@ -141,27 +122,17 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
headers['Content-Type'] = 'application/json'; headers['Content-Type'] = 'application/json';
headers.cookie = getSheinCookie() headers.cookie = getSheinCookie()
request.params = formatParams(request.params) request.params = formatParams(request.params)
let _url = request.url + (request.params ? ('?' + request.params) : '') let _url = request.url + (request.params ? ('?' + request.params) : '')
Promise.resolve().then(() => fetch(_url, { Promise.resolve().then(() => fetch(_url, {
'headers': headers, 'headers': headers, 'method': request.method, 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors'
'method': request.method,
'referrerPolicy': 'no-referrer',
'credentials': 'include',
'body': JSON.stringify(request.data),
'mode': 'cors'
})).then((res) => { })).then((res) => {
resolve(res.json()); resolve(res.json());
}); });
}).then(sendResponse); }).then(sendResponse);
} else if (request.type == 'notify') { } else if (request.type == 'notify') {
chrome.notifications.create( chrome.notifications.create("" + Math.random(), {
"" + Math.random(), { type: "basic", title: "TEMU助手", message: "您店铺【" + request.mallName + "】的商品【" + request.productName + "】成功加入发货台,请尽快处理", iconUrl: "./icons/48.png"
type: "basic", }, null)
title: "TEMU助手",
message: "您店铺【" + request.mallName + "】的商品【" + request.productName + "】成功加入发货台,请尽快处理",
iconUrl: "./icons/48.png"
}, null
)
} }
return true; return true;
@@ -176,31 +147,28 @@ chrome.action.onClicked.addListener(function () {
}); });
chrome.webRequest.onSendHeaders.addListener(details => { chrome.webRequest.onSendHeaders.addListener(details => {
if (details.url && (details.url.indexOf('joinDeliveryGoodsOrderPlatform') != -1)) { if (details.url && (details.url.indexOf('joinDeliveryGoodsOrderPlatform') != -1)) {
details.requestHeaders.push({ details.requestHeaders.push({
name: 'Referer', name: 'Referer', value: 'https://kuajing.pinduoduo.com/main/order-manage'
value: 'https://kuajing.pinduoduo.com/main/order-manage'
}) })
for (let i = 0 ; i < details.requestHeaders.length; i++) { for (let i = 0; i < details.requestHeaders.length; i++) {
if (details.requestHeaders[i].name == 'Origin') { if (details.requestHeaders[i].name == 'Origin') {
details.requestHeaders[i].value = 'https://kuajing.pinduoduo.com' details.requestHeaders[i].value = 'https://kuajing.pinduoduo.com'
break; break;
} }
} }
} else if (details.url && (details.url.indexOf('mms/userInfo') != -1)) { } else if (details.url && (details.url.indexOf('mms/userInfo') != -1)) {
details.requestHeaders.push({ details.requestHeaders.push({
name: 'Referer', name: 'Referer', value: 'https://kuajing.pinduoduo.com/main/order-manage'
value: 'https://kuajing.pinduoduo.com/main/order-manage'
}) })
for (let i = 0 ; i < details.requestHeaders.length; i++) { for (let i = 0; i < details.requestHeaders.length; i++) {
if (details.requestHeaders[i].name == 'Origin') { if (details.requestHeaders[i].name == 'Origin') {
details.requestHeaders[i].value = 'https://kuajing.pinduoduo.com' details.requestHeaders[i].value = 'https://kuajing.pinduoduo.com'
break; break;
} }
} }
} }
}, }, {urls: ["<all_urls>"]}, ["requestHeaders", "extraHeaders"]);
{urls: ["<all_urls>"]},["requestHeaders", "extraHeaders"]);
function getCookie() { function getCookie() {
@@ -254,4 +222,4 @@ function formatParams(data) {
arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name])) arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]))
} }
return arr.join("&") return arr.join("&")
} }

View File

@@ -1,49 +1,46 @@
import SparkMd5 from 'spark-md5' import SparkMd5 from 'spark-md5'
export function getImageMd5(imageUrl) { export function getImageMd5(imageUrl) {
/*return new Promise((resolve, reject) => { /*return new Promise((resolve, reject) => {
fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象 fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象
.then((blobData) => { .then((blobData) => {
const reader = new FileReader(); const reader = new FileReader();
// 读取Blob对象的内容
reader.onloadend = function() {
let spark = new SparkMd5()
spark.appendBinary(this.result);
let md5 = spark.end()
console.log(md5)
console.log(this.result)
//resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})}); // 读取Blob对象的内容
resolve({md5, imageData: this.result}); reader.onloadend = function() {
}; let spark = new SparkMd5()
spark.appendBinary(this.result);
reader.readAsBinaryString(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法 let md5 = spark.end()
console.log(md5)
console.log(this.result)
//resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})});
}) resolve({md5, imageData: this.result});
};
});*/ reader.readAsBinaryString(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法
return new Promise((resolve, reject) => {
fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象
.then((blobData) => {
const reader = new FileReader();
// 读取Blob对象的内容
reader.onloadend = function() {
let spark = new SparkMd5.ArrayBuffer()
spark.append(this.result);
let md5 = spark.end()
//resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})}); })
resolve({md5, imageData: this.result});
};
reader.readAsArrayBuffer(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法
});*/
})
}); return new Promise((resolve) => {
} fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象
.then((blobData) => {
const fileName = imageUrl.match(/\/([^/]+)$/).at(-1)
const reader = new FileReader();
// 读取Blob对象的内容
reader.onloadend = function () {
const spark = new SparkMd5.ArrayBuffer()
spark.append(reader.result);
const md5 = spark.end()
// formData.append('md5', md5)
//resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})});
const image = {blobData, fileName}
resolve({md5, image});
};
reader.readAsArrayBuffer(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法
})
});
}

View File

@@ -2,10 +2,10 @@
<div> <div>
<ai-list class="list"> <ai-list class="list">
<ai-title <ai-title
slot="title" slot="title"
title="速卖通采集" title="速卖通采集"
tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态" tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态"
isShowBottomBorder> isShowBottomBorder>
</ai-title> </ai-title>
<template slot="content"> <template slot="content">
<div class="content"> <div class="content">
@@ -15,10 +15,10 @@
<label style="width:80px">店铺</label> <label style="width:80px">店铺</label>
<el-select v-model="search.mallId" :clearable="true" @change="search.current =1, getList()" placeholder="请选择店铺" size="small"> <el-select v-model="search.mallId" :clearable="true" @change="search.current =1, getList()" placeholder="请选择店铺" size="small">
<el-option <el-option
v-for="item in $store.state.mallList" v-for="item in $store.state.mallList"
:key="item.mallId" :key="item.mallId"
:label="item.mallName" :label="item.mallName"
:value="item.mallId"> :value="item.mallId">
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
@@ -33,12 +33,12 @@
</template> </template>
</ai-search-bar> </ai-search-bar>
<ai-table <ai-table
:tableData="tableData" :tableData="tableData"
:col-configs="colConfigs" :col-configs="colConfigs"
:total="total" :total="total"
style="margin-top: 8px;" style="margin-top: 8px;"
:current.sync="search.current" :size.sync="search.size" :current.sync="search.current" :size.sync="search.size"
@getList="getList"> @getList="getList">
<el-table-column slot="url" label="商品地址" align="left"> <el-table-column slot="url" label="商品地址" align="left">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.url.startsWith('http')"><a class="el-link el-link--primary" :href="scope.row.url" target="_blank">{{ scope.row.url }}</a></div> <div v-if="scope.row.url.startsWith('http')"><a class="el-link el-link--primary" :href="scope.row.url" target="_blank">{{ scope.row.url }}</a></div>
@@ -56,12 +56,12 @@
</ai-list> </ai-list>
<ai-dialog <ai-dialog
title="采集" title="采集"
:visible.sync="copyFromDlgShow" :visible.sync="copyFromDlgShow"
:close-on-click-modal="false" :close-on-click-modal="false"
width="790px" width="790px"
customFooter customFooter
@close="handleClose"> @close="handleClose">
<ai-copy-from-ali-express v-if="copyFromDlgShow" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-ali-express> <ai-copy-from-ali-express v-if="copyFromDlgShow" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-ali-express>
</ai-dialog> </ai-dialog>
</div> </div>
@@ -70,42 +70,43 @@
<script> <script>
import AiCopyFromAliExpress from "@/components/AiCopyFromAliExpress.vue"; import AiCopyFromAliExpress from "@/components/AiCopyFromAliExpress.vue";
import {sendChromeAPIMessage} from '@/api/chromeApi' import {sendChromeAPIMessage} from '@/api/chromeApi'
import { getImageMd5 } from "@/utils/image.js" import {getImageMd5} from "@/utils/image.js"
export default {
name: 'NiubiCopy',
components: {AiCopyFromAliExpress},
data () { export default {
return { name: 'NiubiCopy',
search: { components: {AiCopyFromAliExpress},
current: 1,
size: 10,
type: '2',
mallId: ''
},
colConfigs: [
{ slot: 'url', label: '商品地址', align: 'left' },
{ slot: 'type', label: '来源', width: '100px', align: 'left'},
{ prop: 'mallName', label: '店铺名称', width: '200px', align: 'left'},
{ prop: 'createTime', label: '复制时间', width: '180px'}
],
tableData: [],
total: 0,
copyFromDlgShow: false,
}
},
created () { data() {
this.getList() return {
}, search: {
current: 1,
size: 10,
type: '2',
mallId: ''
},
methods: { colConfigs: [
async getList () { {slot: 'url', label: '商品地址', align: 'left'},
let res2 = await getImageMd5('http://temu.jjcp52.com/dist/test.png') {slot: 'type', label: '来源', width: '100px', align: 'left'},
console.log(res2) {prop: 'mallName', label: '店铺名称', width: '200px', align: 'left'},
{prop: 'createTime', label: '复制时间', width: '180px'}
let res3 = await sendChromeAPIMessage({ ],
tableData: [],
total: 0,
copyFromDlgShow: false,
}
},
created() {
this.getList()
},
methods: {
async getList() {
const image = 'http://temu.jjcp52.com/dist/test.png'
let res2 = await getImageMd5(image), res4
Promise.all([
sendChromeAPIMessage({
url: 'marvel-mms/cn/api/kiana/gmp/bg/phoenix/api/material/create', url: 'marvel-mms/cn/api/kiana/gmp/bg/phoenix/api/material/create',
needMallId: true, needMallId: true,
mallId: '634418212443160', mallId: '634418212443160',
@@ -115,53 +116,49 @@ import { getImageMd5 } from "@/utils/image.js"
{ {
materialType: 1, materialType: 1,
materialMd5: res2.md5, materialMd5: res2.md5,
materialName: "test.png" materialName: "test"
} }
] ]
} }
}) }),
let res4 = await sendChromeAPIMessage({ sendChromeAPIMessage({
url: 'galerie/business/get_signature?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag', url: 'galerie/business/get_signature?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag',
needMallId: true, needMallId: true,
mallId: '634418212443160', mallId: '634418212443160',
data: { data: {
bucket_tag: "product-material-tag" bucket_tag: "product-material-tag"
} }
}) }).then(res => res4 = res)
]).then(() => sendChromeAPIMessage({
let res5 = await sendChromeAPIMessage({ url: 'https://kuajing-file.pinduoduo.com/api/galerie/v3/store_image?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag',
url: 'https://kuajing-file.pinduoduo.com/api/galerie/v3/store_image?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag', isFormData: true,
isFormData: true, data: {
data: { url_width_height: true,
url_width_height: true, image,
image: new Uint8Array(res2.imageData), upload_sign: res4.result.signature
upload_sign: res4.result.signature }
} })).then(() => this.$http.post('/api/copyProduct/myPage', null, {
}) params: {
console.log(res5) ...this.search
}
this.$http.post('/api/copyProduct/myPage',null,{ })).then(res => {
params: { this.tableData = res.data.records
...this.search this.total = res.data.total
} })
}).then(res => { },
this.tableData = res.data.records beforeCopy() {
this.total = res.data.total this.copyFromDlgShow = true
}) },
}, handleClose() {
beforeCopy() { this.copyFromDlgShow = false
this.copyFromDlgShow = true },
}, // 添加模板成功
handleClose() { handleSuccess() {
this.copyFromDlgShow = false this.copyFromDlgShow = false
}, this.getList()
// 添加模板成功
handleSuccess() {
this.copyFromDlgShow = false
this.getList()
}
} }
} }
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

13895
yarn.lock

File diff suppressed because it is too large Load Diff