我正在研究一个简单的拖放/输入按钮文件上传组件。在以下组件中,通过拖放或输入按钮获取文件:
反应组件1:
import React, {useState, useEffect} from 'react';
import ReactDOM from 'react-dom';
function ReceiptUploadPortal(props) {
const {element, uploadFile} = props;
const [errors, setErrors] = useState([]);
const [dropzoneActive, setDropzoneActive] = useState(false);
const [file, setFile] = useState();
const allowedTypes = ['image/jpg', 'image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'application/pdf'];
useEffect(() => {
const isValidSize = file && file.size > 6 * 1024;
const isValidType = file && allowedTypes.includes(file.type);
if (isValidSize && isValidType) {
setErrors([]);
uploadFile(file);
} else {
if (file && !isValidSize) setErrors([...errors, 'file exceeds maximum allowed size']);
if (file && !isValidType) setErrors([...errors, 'unsupported file type, please use a jpg file extension']);
}
}, [file])
function handleDragOver(event) {
event.preventDefault();
setDropzoneActive(true);
setErrors([]);
}
function handleDrop(event) {
event.preventDefault();
if (event.dataTransfer.files.length === 1) {
setFile(event.dataTransfer.files[0]);
} else {
setErrors(['too many files, please upload one image at a time'])
}
setDropzoneActive(false)
}
function handleFileSelect(event) {
setErrors([]);
setFile(event.target.files[0]);
}
return ReactDOM.createPortal(
<div className="receipt-upload-widget-container">
<div className="file-info-wrapper">
<div className="file-info">
<span>FILE TYPE</span><br />
<span>JPG</span>
</div>
<div className="file-info">
<span>MAX SIZE</span><br />
<span>6 MB</span>
</div>
</div>
<div
className={`file-upload-drop-zone ${dropzoneActive ? 'active' : ''}`}
onDrop={(event) => handleDrop(event)}
onDragOver={(event) => handleDragOver(event)}>
<p>
Drag & Drop<br />
or upload your image manually
</p>
</div>
<div className="file-input-wrapper">
<label>
Upload
<input
type="file"
accept="image/*"
onChange={(event) => handleFileSelect(event)} />
</label>
<p>{file && file.name}</p>
</div>
<div className="fileErrors">
{errors.map((error, index) => <div className="fileError" key={index}>{error}</div>)}
</div>
</div>, element
);
}
导出默认的ReceiptUploadPortal;
反应组件2:
import React, {useState} from 'react';
import ReceiptUploadPortal from './ReceiptUploadPortal';
import {receiptUpload} from '../../api/FileUploadService';
import NotificationComponent from '../../ui-components/NotificationComponent';
import { successNotification, errorNotification } from '../../helpers/notficationHelper';
function ReceiptUploadContainer() {
const receiptUploadWidgets = [...document.querySelectorAll(`div[data-widget='ReceiptUpload']`)];
const [notification, setNotfication] = useState({
...successNotification,
onClosed: () => setNotfication({...notification, show: false})
});
async function handleUpload(file) {
const req = await receiptUpload(file);
if (req) {
setNotfication({
...notification,
show: true
})
} else {
setNotfication({
...notification,
...errorNotification,
show: true
});
}
}
return (
<div id="ReceiptUploadContainer">
{receiptUploadWidgets.map((element, index) =>
<ReceiptUploadPortal
key={index}
element={element}
uploadFile={(file) => handleUpload(file)} />
)}
<NotificationComponent {...notification}/>
</div>
);
}
export default ReceiptUploadContainer
然后这会触发服务被调用,这是发生错误的地方...
服务:
import axios from 'axios';
import { urls } from './Urls';
import { getAccountInfo } from './GigyaService';
import { getAWSHeaders } from '../helpers/getAWSHeaders';
export async function receiptUpload(file) {
const account = await getAccountInfo();
const headers = getAWSHeaders(account);
const presignUrl = await axios.post(urls.fileUpload.presignUpload, {fileName: file.name}, {headers}).then(res => res.data);
const fileUpload = presignUrl && await axios.put(presignUrl.presignUrl, file, {'Content-Type': file.type}).then(res => res.status);
const fileId = fileUpload && await axios.post(urls.fileUpload.receiptUpload, {file_name: file.name}, {headers}).then(res => res.data);
const receiptSubmit = fileId && await axios.post(urls.fileUpload.receiptSubmit, {
id_type: 'third_party_id',
file_id: fileId.file_id
}, {headers}).then(res => res.data);
return receiptSubmit;
}
一切正常,直到我尝试将实际文件发布到S3为止。
意思是,我能够获取预签名的网址。但是,当我上传文件时,收到200响应,没有数据负载,并且在S3中可以看到文件不存在。
这当然会导致接下来的两个请求失败。
对我可能在这里做错的任何想法吗?