[Halo Sobat,]
Berikut cara upload file menggunakan XHR. Saya menggunakan framework vuejs untuk ini, saya harap kalian sudah paham menggunakan vuejs + vuetify. Dan berikut adalah sample codenya
img-drop.vue
<template>
<v-container>
<div class="helper"></div>
<div
class="drop display-inline align-center"
@dragover.prevent
@drop="onDrop"
>
<div class="helper"></div>
<label v-if="image.length == 0" class="btn display-inline">
<div>SELECT OR DROP AN IMAGE</div>
<div style="font-size: 8px; text-align: center">accepted image</div>
<input
type="file"
:multiple="multiple"
name="image"
@change="onChange"
/>
</label>
<div
class="hidden display-inline align-center"
v-else
v-bind:class="{ image: true }"
>
<div v-for="(k, v) in image" :key="v" class="flex">
<v-img
v-if="['.jpeg', '.jpg', '.png'].includes(getExt(k.savename))"
:src="k.url"
contain
tile
max-height="200"
max-width="250"
class="img"
>
<v-fade-transition>
<v-overlay absolute color="#036358">
<v-btn outlined x-small @click="print(k.url, k.savename)"
>DOWNLOAD</v-btn
>
<v-btn
class="ml-2"
outlined
color="red"
x-small
@click="removeFile(k)"
>DELETE</v-btn
>
</v-overlay>
</v-fade-transition>
</v-img>
<div v-else style="max-height: 60px; max-width: 100px" class="img">
<div>
<v-btn outlined x-small @click="print(k.url, k.savename)"
>DOWNLOAD</v-btn
>
<v-btn
class="ml-2"
outlined
color="red"
x-small
@click="removeFile(k)"
>DELETE</v-btn
>
</div>
</div>
</div>
</div>
</div>
</v-container>
</template>
<script>
export default {
name: "image-drop",
props: {
multiple: null,
id: null,
},
data() {
return {
image: [],
acceptMime: ["image/jpeg", "image/png"],
};
},
methods: {
onDrop: function (e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files;
if (!this.multiple && files.length > 1) {
console.log(`Tidak dapat meng-upload lebih dari 1 file sekaligus.`);
return;
}
this.onPicked(files);
},
onPicked(files) {
let image = [];
if (files.length > 0) {
for (let i = 0; i < files.length; i++) {
let x = files[i].name;
if (x.lastIndexOf(".") <= 0) {
return;
}
let type = files[i].type;
let valid = this.acceptMime.indexOf(type) !== -1;
if (!valid) {
console.log(`jenis ekstensi tidak didukung`);
return false;
}
const fr = new FileReader();
fr.readAsDataURL(files[i]);
fr.addEventListener("load", () => {
image.push({
id: i + 1,
uid: this.id,
size: Math.round(files[i].size / 1000),
isAllow: files[i].size / 1024 / 1024 > 2 ? false : true,
type: files[i].type,
name: x,
savename: this.buildName(x),
url: fr.result,
file: files[i],
filename: this.buildName(x),
mime_type: files[i].type,
filesize: `${Math.round(files[i].size / 1000)} kB`,
});
});
}
}
let interval;
interval = setInterval(() => {
if (image.length > 0) {
this.$emit("value", image);
this.image = image;
clearInterval(interval);
}
}, 50);
},
onChange(e) {
var files = e.target.files;
this.onPicked(files);
},
removeFile(k) {
if (k) {
this.image = this.image.filter((e) => e.savename != k.savename);
this.$emit("remove", k);
}
},
// untuk moment() saya menggunakan library dayjs
buildName(name) {
const u = moment().format("DDMMYYYYHHmmss.SSS");
const l = name.length;
const i = name.lastIndexOf(".");
const e = name.substring(i, l);
name = name.substr(0, i);
let newname = `${name}-${u}`;
let filename = newname;
filename = filename.replace(
/([~!@#$%^&*()_+=.`{}\[\]\|\\:;'<>,\/? ])+/g,
"-"
);
return filename + e;
},
},
};
</script>
<style scoped>
*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-touch-callout: none;
}
.flex {
display: flex;
}
.btn {
background-color: #f2f2f2;
border: 0;
color: black;
cursor: pointer;
display: inline-block;
font-weight: bold;
padding: 15px 35px;
position: relative;
}
input[type="file"] {
position: absolute;
opacity: 0;
z-index: -1;
}
.align-center {
text-align: center;
}
.helper {
height: 100%;
display: inline-block;
vertical-align: middle;
width: 0;
}
.hidden {
display: none !important;
}
.hidden.image {
display: inline-block !important;
}
.display-inline {
display: inline-block;
vertical-align: middle;
}
.img {
border: 1px solid #b71c1c;
display: inline-block;
height: auto;
max-height: 80%;
max-width: 80%;
width: auto;
}
.drop {
background-color: #f2f2f2;
border: 4px dashed #ccc;
background-color: #f2f2f2;
border-radius: 2px;
height: auto;
max-height: 400px;
max-width: 500px;
width: 100%;
}
.drop:hover {
border: 4px dashed #b71c1c;
}
</style>
kemudian untuk memanggil file tersebut seperti berikut ini
Home.vue
<template>
<v-container fluid fill-height>
<v-row align="center" justify="center">
<v-col sm="12" lg="12" md="12" xl="12" align-self="center">
<image-drop :multiple="false" @value="onUpload"></image-drop>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
components: {
ImgDrop: () => import(`@/components/ImageDrop.vue`)
},
data() {
return {};
},
methods: {
onUpload(v){
const file = v[0].file
this.uploadFile(`http://yourAPI.com`, '/', file, (res) => {
console.log(`response callback`, res)
}
},
// path is target_path on your backend
uploadFile: (url, path = "/", upload = null, callback) => {
let xhr = new XMLHttpRequest();
let fd = new FormData();
fd.append("target_path", path);
if (upload && Array.isArray(upload)) {
for (let i = 0; i < upload.length; i++) {
fd.append("upload[]", upload[i].file, upload[i].filename);
}
} else {
fd.append("upload", upload.file, upload.filename);
}
console.log("fd", fd);
xhr.open("POST", url, true);
xhr.onprogress = function () {
console.log(`loading start`);
};
xhr.onerror = function () {
console.log(`loading end`);
if (typeof callback === "function") {
callback({
status_code: "error",
status_code: "error",
status_message: "Terjadi masalah saat upload data.",
});
}
};
xhr.onload = function () {
let res = xhr.response;
xhr.readyState == 4 && xhr.status == 200
? console.log("Success.")
: console.log("Failed.");
if (typeof callback === "function") {
callback(res);
}
};
xhr.send(fd);
},
}
};
</script>
kurang lebih tampilannya akan seperti berikut ini
Untuk API bisa cek disini ya https://dev.to/irpankusuma/bag-2-upload-with-expressjs-api-2lbi
Top comments (0)