
Dropzonejs를 이용한 Drag & Drop 파일 업로드 구현
Dropzonejs를 이용해 Drag & Drop 파일 업로드 기능을 구현했다. form 페이지에서 업로드 이미지를 추가하고 submit 버튼을 클릭했을 때 서버로 이미지 파일이 업로드되도록 했고 추가된 이미지 파일을 삭제했을 때 서버에 저장된 이미지도 삭제되도록 기능을 구현했다. 스크립트 코드 중 일부는 jQuery를 이용하기 때문에 함께 로드되어야 한다.
<form name="fname">
<label for="fld">필드</label>
<input type="text" name="fld" id="fld" value="">
<div class="dropzone" id="fileDropzone"></div>
</form>
form은 위와 같이 추가적인 input 필드와 dropzone이 포함되어 있다. Dropzonejs 사용을 위해 스크립트 파일을 로드한다.
<script src="./js/dropzone.js"></script>
Dropzonejs 실행을 위한 설정 등은 아래의 코드로 한다. 업로드 파일은 최대 2개, 이미지 파일만 업로드 하도록 설정했다. 서버의 파일도 삭제하기 위해 removefile 을 새로 설정했다. 업로드 이미지 파일이 없을 때도 form submit을 위해 getQueuedFiles() 를 이용해 처리했다.
<script>
Dropzone.options.fileDropzone = {
url: './fileUpload.php',
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 2,
maxFiles: 2,
maxFilesize: 1,
acceptedFiles: 'image/*',
addRemoveLinks: true,
removedfile: function(file) {
var srvFile = $(file._removeLink).data("srvFile");
$.ajax({
type: 'POST',
async: false,
cache: false,
url: './fileDelete.php',
data: { file: srvFile }
});
var _ref;
(_ref = file.previewElement) != null ? _ref.parentNode.removeChild(file.previewElement) : void 0;
setFilesName();
return;
},
init: function() {
var fileDropzone = this;
// Uploaded images
// First change the button to actually tell Dropzone to process the queue.
document.querySelector("button[type=submit]").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
// Form check
if(checkForm()) {
if (fileDropzone.getQueuedFiles().length > 0) {
fileDropzone.processQueue();
} else {
setFilesName();
submitForm();
}
}
});
// Append all the additional input data of your form here!
this.on("sending", function(file, xhr, formData) {
formData.append("token", $("input[name=token]").val());
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function() {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
});
this.on("successmultiple", function(files, response) {
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
var obj = JSON.parse(response);
for(i=0; i<files.length; i++) {
$(files[i]._removeLink).data('srvFile', obj[files[i].name]);
}
setFilesName();
// form submit
submitForm();
});
this.on("errormultiple", function(files, response) {
// Gets triggered when there was an error sending the files.
// Maybe show form again, and notify user of error
});
}
};
</script>
서버 업로드 파일 처리를 위한 Class는 아래와 같다.
<?php
/**
* File Upload class
*/
class FILEUPLOAD
{
protected $dest;
protected $ext;
protected $chunkTime;
public function __construct()
{
if(!is_writable(FILES_PATH))
throw new \Exception('Unable to write');
$dest = FILES_PATH.DIRECTORY_SEPARATOR.'tmp';
if(!is_dir($dest)) {
mkdir($dest, 0755);
chmod($dest, 0755);
}
$this->dest = $dest;
$this->ext = array( 1 => 'gif', 2 => 'jpg', 3 => 'png');
$this->chunkTime = 86400 * 2;
}
public function fileName()
{
list($usec) = explode(' ', microtime());
$usec = preg_replace('#[^0-9]#', '', $usec);
return md5(date('YmdHis', time()).$usec);
}
public function chunkDelete()
{
foreach (scandir($this->dest) as $c) {
if ($c == '.' || $c == '..')
continue;
$f = $this->dest . DIRECTORY_SEPARATOR . $c;
if (is_dir($f))
rmdir($f);
if (time() - filemtime($f) > $this->chunkTime)
unlink($f);
}
}
public function upload()
{
$result = array();
// chunk delete
$this->chunkDelete();
$cnt = count($_FILES['file']['name']);
for ($i = 0; $i < $cnt; $i++) {
$file = $_FILES['file']['tmp_name'][$i];
if ($file) {
$size = getimagesize($file);
if ($size[2] >= 1 && $size[2] <= 3) {
while (1) {
$name = $this->fileName();
$dest = $this->dest.DIRECTORY_SEPARATOR.$name.'.'.$this->ext[$size[2]];
if(is_file($dest)) {
usleep(10);
continue;
}
break;
}
move_uploaded_file($file, $dest);
$result[$_FILES['file']['name'][$i]] = str_replace(NT_FILES_PATH, '', $dest);
}
}
}
return $result;
}
}
업로드 파일 처리를 위한 fileUpload.php 파일은 아래와 같다.
<?php
define('FILES_PATH', __DIR__.'/files');
$result = array();
if (!empty($_FILES)) {
$file = new FILEUPLOAD();
$result = $file->upload();
}
die(json_encode($result));
업로드 파일 삭제를 위한 fileDelete.php 파일은 아래와 같다.
<?php
define('FILES_PATH', __DIR__.'/files');
$file = $_POST['file'];
if ($file) {
$path = FILES_PATH.$file;
if (is_file($path))
unlink($path);
}
파일 삭제의 경우 파일명만 알면 삭제가 되기 때문에 추가적인 보안조치가 있어야 한다.
추가 내용으로 서버에 업로드된 파일의 썸네일을 Dropzone 에 표시되게 하려면 아래와 같은 코드가 Dropzonjs 설정 스크립트 코드 중 // Uploaded images 다음에 추가하면 된다.
var mockFile;
var fileCount = 0;
$.getJSON("./getFiles.php", function(data) {
$.each(data, function(key, value) {
mockFile = { name: value.name, size: value.size };
fileDropzone.emit("addedfile", mockFile);
fileDropzone.emit("thumbnail", mockFile, value.data);
fileDropzone.emit("complete", mockFile);
$(mockFile._removeLink).data("srvFile", value.path);
fileCount++;
});
fileDropzone.options.maxFiles = fileDropzone.options.maxFiles - fileCount;
});
getFiles.php 파일의 아래와 같다.
<?php
define('FILES_PATH', __DIR__.'/files);
$files = array();
for($i = 1; $i <= 2; $i++) {
if ($row['file'.$i]) {
$file = FILES_PATH.$row['file'.$i];
if (is_file($file)) {
$size = filesize($file);
$name = basename($file);
$path = str_replace(FILES_PATH, '', $file);
$mime = mime_content_type($file);
$data = 'data:'.$mime.';base64,'.base64_encode(file_get_contents($file));
$files[] = array(
'name' => $name,
'size' => $size,
'path' => $path,
'data' => $data
);
}
}
}
die(json_encode($files));
서버에 업로드된 이미지의 사이즈가 큰 경우 썸네일이 정상적으로 표시되지 않을 수 있는데 이 때는 css 코드를 이용해 썸네일 사이즈를 지정해준다.
.dz-image img {width: 120px; height: 120px}
Leave Dropzonejs를 이용한 Drag & Drop 파일 업로드 구현 to:
Read more #kr posts
Best Posts From 편리
We have not curated any of chicpro's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From 편리
- 쉘스크립트에서 웹서버 권한으로 php 파일 실행하기
- Dropzonejs를 이용한 Drag & Drop 파일 업로드 구현
- Kakao Vision API 사용을 위한 PHP Client
- XMLRPC를 이용한 네이버 블로그 포스팅
- DKMS를 이용한 A2000UA Ubuntu 드라이버 설치
- PECL 이용해 MongoDB PHP Driver 설치
- Ubuntu 16.04에 MongoDB 툴 Robo 3T 설치
- Ubuntu 16.04에 MongoDB 3.6 설치 및 bindIp 설정
- [S5Pro] 2008.09.28 하늘공원
- Ubuntu 16.04에 Postman Native App 설치하기
- 아이폰 사진 리사이즈 무료 앱 Image Resize+
- Typora를 이용해 워드프레스 블로그 포스트를 Steemit에 등록하기
- Ubuntu 16.04에서 ngx_pagespeed 모듈을 포함한 nginx deb 패키지 컴파일
- 우분투 16.04 wine 3.0 설치 후 카카오톡 실행 설정
- Markdown 에디터 Typora