自己踩过坑不想别人也踩坑了 亚马逊S3存储桶直传前端demo复制即可使用
<! DOCTYPE html >
< html lang = " zh-CN" >
< head>
< meta charset = " UTF-8" />
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" />
< title> S3 直传示例</ title>
< style>
.container {
max-width : 600px;
margin : 50px auto;
padding : 20px;
box-shadow : 0 0 10px rgba ( 0, 0, 0, 0.1) ;
border-radius : 8px;
}
.upload-area {
border : 2px dashed #ccc;
padding : 20px;
text-align : center;
margin : 20px 0;
border-radius : 4px;
}
.upload-area.dragover {
background-color : #e1f5fe;
border-color : #2196f3;
}
.progress {
margin-top : 20px;
display : none;
}
.progress-bar {
height : 20px;
background-color : #4caf50;
width : 0%;
transition : width 0.3s;
}
.status {
margin-top : 10px;
color : #666;
}
</ style>
</ head>
< body>
< div class = " container" >
< h1> S3 直传示例</ h1>
< div class = " upload-area" id = " dropZone" >
< p> 拖拽文件到这里或点击选择文件</ p>
< input type = " file" id = " fileInput" style = " display : none" />
< button onclick = " document. getElementById ( 'fileInput' ) . click ( ) " > 选择文件</ button>
</ div>
< div class = " progress" id = " progressContainer" >
< div class = " progress-bar" id = " progressBar" > </ div>
< div class = " status" id = " status" > </ div>
</ div>
</ div>
< script>
const dropZone = document. getElementById ( "dropZone" ) ;
const fileInput = document. getElementById ( "fileInput" ) ;
const progressContainer = document. getElementById ( "progressContainer" ) ;
const progressBar = document. getElementById ( "progressBar" ) ;
const status = document. getElementById ( "status" ) ;
[ "dragenter" , "dragover" , "dragleave" , "drop" ] . forEach ( ( eventName ) => {
dropZone. addEventListener ( eventName, preventDefaults, false ) ;
} ) ;
function preventDefaults ( e ) {
e. preventDefault ( ) ;
e. stopPropagation ( ) ;
}
[ "dragenter" , "dragover" ] . forEach ( ( eventName ) => {
dropZone. addEventListener ( eventName, highlight, false ) ;
} ) ;
[ "dragleave" , "drop" ] . forEach ( ( eventName ) => {
dropZone. addEventListener ( eventName, unhighlight, false ) ;
} ) ;
function highlight ( e ) {
dropZone. classList. add ( "dragover" ) ;
}
function unhighlight ( e ) {
dropZone. classList. remove ( "dragover" ) ;
}
dropZone. addEventListener ( "drop" , handleDrop, false ) ;
fileInput. addEventListener ( "change" , handleFileSelect, false ) ;
function handleDrop ( e ) {
const dt = e. dataTransfer;
const files = dt. files;
handleFiles ( files) ;
}
function handleFileSelect ( e ) {
const files = e. target. files;
handleFiles ( files) ;
}
async function handleFiles ( files ) {
const file = files[ 0 ] ;
if ( ! file) return ;
try {
const response = await fetch ( ` BASEURL?file_name= ${ file. name} ` ) ;
const data = await response. json ( ) ;
if ( data. code === 20000 ) {
progressContainer. style. display = "block" ;
progressBar. style. width = "0%" ;
status. textContent = "开始上传..." ;
const xhr = new XMLHttpRequest ( ) ;
xhr. upload. onprogress = ( e ) => {
if ( e. lengthComputable) {
const percentComplete = ( e. loaded / e. total) * 100 ;
progressBar. style. width = percentComplete + "%" ;
status. textContent = ` 上传进度: ${ Math. round ( percentComplete) } % ` ;
}
} ;
xhr. onload = ( ) => {
if ( xhr. status === 200 ) {
status. textContent = "上传成功!" ;
status. style. color = "#4CAF50" ;
} else {
status. textContent = "上传失败,请重试" ;
status. style. color = "#f44336" ;
}
} ;
xhr. onerror = ( ) => {
status. textContent = "上传出错,请重试" ;
status. style. color = "#f44336" ;
} ;
xhr. open ( data. data. method, data. data. url) ;
xhr. send ( file) ;
} else {
throw new Error ( data. msg || "获取上传配置失败" ) ;
}
} catch ( error) {
console. error ( "上传出错:" , error) ;
status. textContent = "上传出错: " + error. message;
status. style. color = "#f44336" ;
}
}
</ script>
</ body>
</ html>