I'm currently using FilePond via the Vue-Adapter in my app and it's working fine.
My current, for this question relevant, code looks like this:
<template>
<v-layout>
<v-flex class="text-center">
<FilePond
ref="pond"
name="file"
chunk-uploads="true"
:chunk-size="chunkSize"
class-name="my-pond"
label-idle="Drop files here..."
:allow-multiple="allowMultiple"
:files="myFiles"
:server="server"
#init="handleFilePondInit"
#error="error"
#processfile="updatefiles"
#addfile="testlog"
/>
</v-flex>
</v-layout>
</template>
The server-Property looks like this:
computed: {
headers() {
return {
Authorization: this.$auth.getToken('local'),
projectId: this.projectId,
};
},
server() {
return {
url: 'http://localhost:3001/api/filepond/',
process: {
url: 'process',
headers: this.headers,
},
patch: {
url: 'patch?id=',
headers: this.headers,
},
};
},
chunkSize() {
return this.$config.chunk_size_byte;
},
},
This setup does work fine. FilePond works as intended and my custom headers get injected additionally to the headers FilePond provides. Now I ran into an issue, where I need the Filename also on a process-Request, which doesn't usually get sent when a patch-Request follows.
I found this GitHub Issue, which is basically my exact issue.
If I however change my computed server-value to the following code, my headers don't get applied at all.
server() {
return {
url: 'http://localhost:3001/api/filepond/',
process: {
url: 'process',
headers: (file, metaData) => ({
Authorization: this.$auth.getToken('local'),
projectId: this.projectId,
filename: file.filename,
}),
},
patch: {
url: 'patch?id=',
headers: this.headers,
},
};
},
So after trying a lot out, it seems like there's a bug with vue-filepond, where custom Header-Functions are only applied, when uploading files with fileSize > chunkSize.
I opened an issue and Rik provided a workaround for the time being (https://github.com/pqina/vue-filepond/issues/193).
Related
vue2-dropzone is working fine for vue2 but not working for vue3.
With the following code
import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.min.css'
return {
dropzoneOptions: {
autoProcessQueue: false,
addRemoveLinks: true,
url: this.url,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
},
id: null,
myDropZone: null,
supervisorError: ''
}
}
I do have the following error
TypeError: Cannot read property '_c' of undefined vue3
vue3-dropzone
What you are after is vue3-dropzone.
It worked highly similar to the vue2-dropzone package that most of you may have been using with vue2. I myself am one of the contributors to the new vue3-dropzone package. I have just added the example code for those who want to Save Multiple Files at once, as shown below:
Example of Saving Multiple Files
<template>
<div>
<div v-bind="getRootProps()">
<input v-bind="getInputProps()" />
<p v-if="isDragActive">Drop the files here ...</p>
<p v-else>Drag 'n' drop some files here, or click to select files</p>
</div>
<button #click="open">open</button>
</div>
</template>
<script>
import { useDropzone } from "vue3-dropzone";
import axios from "axios";
export default {
name: "UseDropzoneDemo",
setup() {
const url = "{your_url}"; // Your url on the server side
const saveFiles = (files) => {
const formData = new FormData(); // pass data as a form
for (var x = 0; x < files.length; x++) {
// append files as array to the form, feel free to change the array name
formData.append("images[]", files[x]);
}
// post the formData to your backend where storage is processed. In the backend, you will need to loop through the array and save each file through the loop.
axios
.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
console.info(response.data);
})
.catch((err) => {
console.error(err);
});
};
function onDrop(acceptFiles, rejectReasons) {
saveFiles(acceptFiles); // saveFiles as callback
console.log(rejectReasons);
}
const { getRootProps, getInputProps, ...rest } = useDropzone({ onDrop });
return {
getRootProps,
getInputProps,
...rest,
};
},
};
</script>
As stated in this post: https://github.com/rowanwins/vue-dropzone/issues/578
It looks like vue-dropzone does not support Vue3 as of right now, I mean the mantainer was already struggling to manage the vue 2 and asked for help so it seems legit.
Maybe give a look to this vue3 one: https://github.com/Yaxian/vue3-dropzone
Here is a list of available alternatives: https://github.com/vuejs/awesome-vue#drag-and-drop
well, we're using this package for our production builds:
Vue3 Library Component for drag’n’drop file uploads with image previews.
https://github.com/darknessnerd/drop-zone
Following basic example in the docs, yet sound doesn't play. I see the mp3 file in Network tab but it's 90KB instead of 5MB so I suppose it doesn't load properly.
I tried different paths: src: ['#/assets/audios/test.mp3'], `src: ['../assets/audios/test.mp3']. Nothing works. No console error. Why is it not working?
<template>
<div class="container">
<button #click="play">
PLAY
</button>
</div>
</template>
<script>
import { Howl, Howler } from 'howler'
export default {
data () {
return {
sound: ''
}
},
mounted () {
this.sound = new Howl({
src: ['test.mp3']
})
},
methods: {
play () {
this.sound.play()
}
}
}
</script>
It sounds like you're trying to load an asset URL for src.
The asset URL needs to be required so that Webpack resolves the actual URL to the file.
Errors are silently ignored, but you can set onloaderror to handle them.
export default {
mounted () {
this.sound = new Howl({
// 1
src: [
require('#/assets/audios/test.mp3')
],
// 2
onloaderror(id, err) {
console.warn('failed to load sound file:', { id, err })
}
})
}
}
I have an API endpoint which works on PUT Request to update User info such as user avatar. This API is built on Django. In my Frontend, I'm using NUXT to upload the file using FilePond, I did the following:
<template>
<section class="section">
<div class="container">
<file-pond
name="test"
ref="pond"
label-idle="Drop files here..."
v-bind:allow-multiple="true"
accepted-file-types="image/jpeg, image/png"
/>
<vs-button success #click='userinfo_put_avatar'>File upload data</vs-button>
</div>
</section>
</template>
<script>
import vueFilePond from 'vue-filepond';
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
let FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview);
export default {
components: {
FilePond,
},
methods: {
async userinfo_put_avatar() {
let file = this.$refs.pond.getFiles(0)
let fileupload = new FormData();
fileupload.append('avatar', file)
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
let data = await this.$axios.put('user-info/', fileupload, config);
},
}
};
</script>
This works for me very well. But I want the feature of Filepond to show the upload status with the spinning svg, when in process of uploading and when completed show the green status.
I tried using the pond.processFile(0) but it doesnot upload the file.
I tried using the FilePond.setOptions() but it gives me an error setOptions is not a function. If this could work somehow.
I would be able to overwrite onaddfileprogress event using the following code from GITHUB ISSUE LINK
FilePond.setOptions({
instantUpload: true,
allowImagePreview: false,
server: {
url: '/images',
process: {
url: '/upload',
},
revert: '/revert',
restore: '/restore/',
load: '/load/',
},
onremovefile: function(error, file) {
if (file.serverId) {
let input = document.createElement('input');
input.type = 'hidden';
input.name = 'DeletedFilepondImages';
input.value = file.serverId;
uploadForm.appendChild(input);
}
},
onaddfilestart: function(file) {
console.log(`onaddfilestart`);
buttonForm.classList.add('filepondUpload');
buttonForm.setAttribute('disabled', 'true');
},
onaddfileprogress(file, progress) {
console.log(`onaddfileprogress`);
buttonForm.classList.remove('filepondUpload');
buttonForm.removeAttribute('disabled');
},
});
// get a reference to the input element
const filepondInput = document.querySelector(
'#filepondFileUploader input[type="file"]'
);
// create a FilePond instance at the input element location
const filepondObject = FilePond.create(filepondInput, {
maxFiles: 5,
acceptedFileTypes: ['image/*'],
labelIdle:
'<div class="image-upload__file-upload-content">Add images</div>',
files: filepondInitialFiles,
onprocessfiles() {
console.log('onprocessfiles');
buttonForm.classList.remove('filepondUpload');
buttonForm.removeAttribute('disabled');
},
});
You need to define the server prop on the component. You can use v-bind:server="myServer" and then add it to your component data.
<file-pond
name="test"
ref="pond"
v-bind:server="myServer"/>
export default {
name: 'app',
data: function() {
return {
myServer: {
// server config here
}
};
},
components: {
FilePond
}
};
If you need setOptions, you can import it from vueFilePond
import vueFilePond, { setOptions } from 'vueFilePond'
Anyone know why a sub page crashes when user reloads the page? It is fine when you navigate to the page using nuxt-link from another page (using route params), but when the user reloads/refreshes the page, it will crash.
Here is my sandbox where you can test it out: Codesandbox
Code from nuxt link:
<nuxt-link :to="{name: 'photos-id-title', params: { id: photo.id, title: photo.title }}">
Code from photo details page:
<template>
<section>
<!-- <template v-if="photo"> -->
<img
:id="photo.filename"
:src="photo.url"
class="img-fluid thumbnail rounded"
:alt="photo.title"
/>
<h1 class="h3">{{ photo.title }}</h1>
</section>
</template>
<script>
import { Annotorious } from '#recogito/annotorious'
export default {
data() {
return {
photo: {},
anno: {},
title: this.$route.params.title
}
},
async mounted() {
await this.getPhotoDoc()
this.anno = await new Annotorious({ image: this.photo.filename })
},
methods: {
async getPhotoDoc() {
const docRef = await this.$fireStore
.collection('photos')
.doc(this.$route.params.id)
.get()
try {
if (docRef.exists) {
// data() returns all data about the doc
console.log('got the doc: ', docRef.data())
this.photo = docRef.data()
} else {
console.log('no docs exist')
}
} catch (error) {
console.log('Error getting document:', error)
}
}
},
head() {
return {
title: this.photo.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.photo.description
}
]
}
}
}
</script>
User journey: Click PHOTOS from navbar, select any photo on the page. You shall see a "photo detail" page. Loads fine. Try to refresh the page -- it will crash.
Note: I also have this scaffolded in a regular/plain vue app using Vue-cli and have NO issues. Only seems to be a problem with Nuxt. Must be SSR related?
Thanks for any help...
If you think this is SSR related and the Annotorious plugin might cause the problem try this:
nuxt.config.js add the plugin with mode client
plugins: [
{ src: '~/plugins/client-only.js', mode: 'client' }, // only on client side
]
You can find more information in the nuxtjs docs here
I want to add stripe elements to my nuxt js page However, I got an error
Stripe is not defined
I have inserted the <script src="https://js.stripe.com/v3/"></script> on my nuxt.config.js
Here's the code
head: {
title: process.env.npm_package_name || "",
script: [{ src: "https://js.stripe.com/v3/" }],
link: [
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
]
},
My payment page
<template>
<div>
<div ref="card"></div>
<button v-on:click="purchase">Purchase</button>
</div>
</template>
<script>
let stripe = Stripe("Key"),
elements = stripe.elements(),
card = undefined;
export default {
mounted: function() {
card = elements.create("card");
card.mount(this.$refs.card);
},
methods: {
async purchase() {
let result = await stripe.createToken(card);
}
}
};
</script>
I followed this tutorial and still can't fix it
https://alligator.io/vuejs/stripe-elements-vue-integration/
You are including stripe for into scripts, so it will be loaded in browser. But nuxt is SSR. And the code in your script section will be also executed on server. And on server there no stripe, so it wont work. You need to execute all your code that create Stripe in mounted hook, which is only executed on client