1. input 컨트롤을 이용한 드래그 앤 드롭 업로드 구현
<form action="http://localhost:82/drag&drop/fileUpload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="myfile" id="">
<input type="submit" value="上传文件">
</form>
주의: method="POST", enctype="multipart/form-data", 그리고 type="file" name="myfile"을 반드시 설정해야 합니다. 이 세 가지 중 하나라도 누락되면 백엔드 PHP에서 데이터를 받을 수 없습니다.
물론 파일을 드래그 앤 드롭한 후 submit 버튼을 클릭하면 브라우저가 바쁨 상태가 되고 페이지 새로고침이 시작됩니다. 폼 제출 방식을 사용하면 파일 업로드 시 페이지 새로고침을 피할 수 없지만, 뒤에서 소개할 방식을 사용하면 새로고침 없는 드래그 앤 드롭 업로드를 구현할 수 있습니다.
(백엔드 코드는 FormData + Ajax 방식과 동일하므로 뒷부분을 참고하세요.)
2. FormData + Ajax를 이용한 드래그 앤 드롭 업로드 구현
<div id="dropArea3">文件放置区域</div>
<script>
// 可拖放元素
var area3 = document.getElementById('dropArea3');
// 文件放置区域
area3.ondragover = function(e) {
e.preventDefault();
}
area3.ondrop = function(e) {
e.preventDefault();
var files = e.dataTransfer.files;
if (files && files.length > 0) {
// 输出文件信息
var str = '';
for(var i = 0; i < files.length; i++) {
var file = files[i];
// 在线预览图片也需要先把图片上传到服务器,因为无法获取客户端文件url
// 上传文件直接xhr发送file对象即可
var formData = new FormData();
formData.append('myfile', file);
// JQ方式
// $.ajax({
// type : 'POST',
// url: 'http://localhost:82/drag&drop/fileUpload.php',
/* 必须设置下面两个属性,否则会导致$_FILES收不到数据 */
// processData: false,
// contentType: false,
// data: formData,
// success: function(res){
// console.log('success');
// console.log(res);
// },
// error: function(res) {
// console.log('error');
// }
// });
// 原生JS方式
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:82/drag&drop/fileUpload.php", true);
/* 千千万不能设置,会导致$_FILES收不到数据 */
// xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(formData);
xhr.onload = function(e) {
if (this.status == 200) {
console.log(this.responseText);
}
};
console.log(file);
}
console.log('receive a file');
}
}
</script>
위 코드는 jQuery와 네이티브 JS 두 가지 방식을 소개합니다. 코드를 보면 네이티브 JS를 사용하는 것이 실제로 더 편리하다는 것을 알 수 있습니다 (ContentType을 절대 설정하지 않도록 주의해야 함). 주의해야 할 이 점은 의외로 성공하기 쉽습니다. 반면 jQuery 구현 방식은 이해하기 어렵습니다 (processData와 contentType을 false로 설정해야 하는데, 이걸 어떻게 생각하겠습니까...).
따라서 이 부분은 네이티브 JS로 구현하는 것을 권장합니다. 호환성 측면에서도 드래그 앤 드롭 파일을 지원하는 브라우저라면 표준 xhr도 진작부터 지원했을 것입니다.
3. 백엔드 처리
먼저 한 가지 분명히 할 점은, Ajax로 파일을 전송할 때 POST 메서드를 사용하더라도 전송되는 것은 결국 파일(추가 속성이 있음)이지 일반 문자열이 아닙니다. 따라서 PHP 백엔드에서는 $_FILES 배열로 데이터를 받으며, $_POST 배열이 아닙니다.
<?php
/* 从$_FILES中取,而不是$_POST */
$file = $_FILES['myfile'];
$fileName = $file['name'];
// echo $fileName;
$fileSize = $file['size'];
// echo $fileSize;
if ($fileName != "") {
$rand = rand(100, 999);
$pics = date("YmdHis") . $rand . $fileName;
//上传路径
$filePath = "files/". $pics;
/* tmp_name是定死的,php出于服务器安全性考虑,过滤文件名 */
if (move_uploaded_file($_FILES['myfile']["tmp_name"], $filePath)) {
echo $filePath;
}
}
?>
위의 여러 줄 주석 내용, 특히 move_uploaded_file 함수의 매개변수에 주의하세요. 모르면 절대로 제대로 작성할 수 없습니다.
참고 자료:
- 선배들의 여러 블로그 포스트
아직 댓글이 없습니다