Appearance
看下面代码,ios的qq浏览器上传失败,但是别的浏览器都没有任何问题
问后端也是个小白,说不清二和三,就说是解析失败
tsx
import Taro from '@tarojs/taro'
import React from 'react'
import axios from 'axios'
export default function index() {
const blobAsDataURL = (blob) => {
return new Promise(resolve => {
const fileReader = new FileReader();
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.readAsDataURL(blob);
});
};
const dataURLAsFile = (dataUrl, filename = 'file.jpg') => {
const [type, data] = dataUrl.split(',');
const mime = /:(.*?);/.exec(type)?.pop();
const content = atob(data);
let { length } = content;
const u8arr = new Uint8Array(length);
while (length--) {
u8arr[length] = content.charCodeAt(length);
}
return new File([u8arr], filename, { type: mime });
};
const handleClick = () => {
Taro.chooseImage({
async success(res) {
const tempFilePaths = res.tempFilePaths[0]
const blob = await fetch(tempFilePaths).then(response => {
return response.blob();
});
const dataUrl = await blobAsDataURL(blob);
let file = await dataURLAsFile(dataUrl);
Taro.uploadFile({
url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'file',
formData: {
file
},
success(res) {
const data = res.data
//do something
}
})
}
})
}
return (
<div>
<div onClick={handleClick}>按钮</div>
</div>
)
}那么怎么办,靠人不如靠己,自己手撸一个后端服务试试
测试发现,qq浏览器上传失败的原因是把文件后缀丢失,导致解析图片失败,估计是这款浏览器内部问题,其他浏览器都没有这个问题
解决方法是在上传文件时,把文件名也传递到后端,后端收到文件名后,再根据文件名保存文件
前端代码
tsx
import Taro from '@tarojs/taro'
export default function index() {
const handleClick = () => {
Taro.chooseImage({
async success(res) {
const tempFilePaths = res.tempFilePaths[0]
const fileExtensionMatch = tempFilePaths.match(/\.([0-9a-z]+)(?:[\?#]|$)/i);
const fileExtension = res.tempFiles[0] ? res.tempFiles[0].type.split('/')[1] : 'jpg'; // 默认为 'jpg'
console.log('文件扩展名:', tempFilePaths, fileExtension, fileExtensionMatch);
// 生成新的文件名(包括扩展名)
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
const fileName = `file-${uniqueSuffix}.${fileExtension}`;
console.log('生成的文件名:', fileName);
Taro.uploadFile({
url: 'http://xxx.xx.xx.xx:3000/api/data', //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'file',
formData: {
fileName: fileName
},
success(res) {
const data = res.data
//do something
}
})
}
})
}
return (
<div>
<div onClick={handleClick}>按钮</div>
</div>
)
}后端代码
js
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;
// 创建img目录(如果不存在)
const imgDir = path.join(__dirname, 'img');
if (!fs.existsSync(imgDir)) {
fs.mkdirSync(imgDir, { recursive: true });
console.log('已创建img目录');
}
// 配置CORS
app.use(cors({
origin: 'http://xxx.xx.xx.xx:10086',
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: [
'Content-Type',
'Authorization',
'X-Os-Version',
'X-Device-Id',
'X-Yzh-Language',
'X-App-Type',
'x-yzh-env',
'request-id',
'X-Access-Token',
'X-Member-Id',
'X-App-Id',
'X-Device-Type',
'X-Os'
],
credentials: true
}));
// 处理预检请求
app.options('/api/data', cors());
// 配置multer存储图片到img目录
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, imgDir); // 保存到img目录
},
filename: function (req, file, cb) {
// 使用前端传递的文件名
const fileName = req.body.fileName || file.originalname; // 如果前端没有传递文件名,使用原文件名
console.log(3333,fileName,file.originalname);
// 清理文件名,确保不包含非法字符
const cleanedFileName = fileName.replace(/[:/]/g, '-');
cb(null, cleanedFileName);
}
});
// 过滤只允许图片文件
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true); // 接受图片文件
} else {
cb(new Error('只允许上传图片文件'), false); // 拒绝非图片文件
}
};
const upload = multer({
storage: storage,
fileFilter: fileFilter,
limits: { fileSize: 10 * 1024 * 1024 } // 限制10MB
});
// 处理图片上传并保存
app.post('/api/data', upload.array('file'), (req, res) => {
console.log('\n===== 接收到的表单数据 =====');
console.log('文本字段:', req.body);
if (req.files && req.files.length > 0) {
console.log('\n文件保存信息:');
const savedFiles = req.files.map(file => {
console.log(11,file);
const filePath = path.join(imgDir, req.body.fileName);
console.log(`- 已保存: ${filePath}`);
return {
filename: req.body.fileName,
path: filePath,
size: Math.round(file.size / 1024) + ' KB'
};
});
res.json({
code: 200,
message: `成功保存 ${req.files.length} 张图片到img目录`,
savedFiles: savedFiles
});
} else {
res.status(400).json({
code: 400,
message: '未接收到图片文件'
});
}
});
// 错误处理
app.use((err, req, res, next) => {
console.error('错误:', err.message);
res.status(400).json({
code: 400,
message: err.message
});
});
// 启动服务器
app.listen(port, '0.0.0.0', () => {
console.log(`服务器运行在 http://xxx.xx.xx.xx:${port}`);
console.log(`图片将保存到: ${imgDir}`);
});