How to download a locally stored file in VueJS - html

I have an upload system and I am trying to supply a sample template for users. I have a template stored locally in a subfolder in assets, I would like to access that in my VueJS component and display a link to it on the page. These are the applicaple parts of the file structure:
├──app
│ └──Components
│ └──Uploader.vue
└──assets
└──files
└──Template_Upload.csv
In Uploader.vue I have this line:
<a v-bind:href="item.loc" download>{{item.title}}</a>
And in the export I have this line
data() {
return {
item: {title: 'Upload Template', loc: require('../../assets/files/Template_Upload.csv')}
}
This method works if I have an image. Upon clicking on the link, it downloads the image. However, if I use a .csv or a .xlsx file, errors are thrown upon opening the page. I've tried using
import fileTemplate from "../../assets/files/FileTemplate.csv";
As well, and using fileTemplate as the loc property. This also works if I use a picture. But I'm not able to bring in a document. Is this a limitation I can't get past or is there a different method I can try?
I've also gone into Visual Studio (in other words, the .csproj file), and set the Template_Upload.csv Build Action setting is set to "Content" and the Copy to Ouput Directory setting is set to "Copy Always".
These are the resources I have primarily used thus far:
How to import and use image in a Vue single file component?
What are the various "Build action" settings in Visual Studio project properties and what do they do?

For anyone which doesnt want to use webpack, I solved this issue:
create a folder called files in public
I moved there the files I wanted to download
and Voila, WORKED.
<a href="/files/book.pdf" download>DOWNLOAD</a>

Thanks OverCoder, the solution was indeed to add a CSV Loader in order that adds the locally stored files to the webpack server. For anyone else using webpack, I added this module to my webpack.config.js file:
{
test: /\.(csv|xlsx|xls)$/,
loader: 'file-loader',
options: {
name: `files/[name].[ext]`
}
}
Then I could reference the file easily like this in my template,
<a href="/files/Template_Upload.csv" download>File Template</a>
or this
<a :href="item.loc" download>File Template</a>
using the same data return as I said. Using the require statement with the loader puts the "required" files into the wwwroot/files folder when the project builds. Thanks again, OverCoder, this saved me a lot of time.

Just an extension to the #Judd's answer. If you don't have a webpack.config.js, you can use the vue.config.js file. (just create it in the root, if it doesn't exist)
vue.config.js
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.(csv|xlsx|xls)$/,
loader: 'file-loader',
options: {
name: `files/[name].[ext]`
}
}
],
},
},
};

This works for me;
<a href="../../assets/files/FileTemplate.csv" download>Download</a>
It behaves nicely even in dialogs.

I was on Laravel, and I follow this tuto to get mine working:
create an FileController, add a download method
public function downloadFile($file){
$path = public_path().'/app/upload-folder/'.$file; // or storage_path() if needed
$header = [
'Content-Type' => 'application/*',
];
return response()->download($path, $file, $header);
}
create an api entry point in api.php
Route::get('download/upload-folder/{file}', 'FileController#downloadFile');
create a method which uses axios
async downloadTemplateFile(file){
axios.get('/download/template/file/'+file, {responseType: 'arraybuffer'}).then(res=>{
let blob = new Blob([res.data], {type:'application/*'})
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = file
link._target = 'blank'
link.click();
})
}
call from vue template
<li>Download the CSV template here</li>
Hope this will helps others ;)

Place the file you want to download in the public folder as it is the root folder of your application.
File Structure Image ->
Image Link
Give the href link as below :
<a :href="'/files/SampleFile.xlsx'" class="btn btn-primary" download>Sample File</a>
You can provide any file in the folder structure. For example : .pdf, .xlsx, .png etc
Please note, give the href as :href with file path as " 'your file path' "
Tested and Working on Vue3

Try this:
Download

Try this way and it is with a button:
<a href="/files/Template_Upload.csv" download>
<button class="btn btn-primary">Download</button>
</a>

Related

How to display image using address in DB using Vue.js?

I'm trying to display an image saved with Django REST. When saving, the path that is indicated in the database is "user_avatars/user1/avatar1.jpg".
When I upload an object from the database to the frontend (Vue.js 3) using the API, the address is displayed as "http://127.0.0.1:8000/uploads/user_avatars/user1/avatar1.jpg"
Here you can see that I use "/uploads/" as the MEDIA_URL folder in Django. However, trying to display an image from this link does nothing:
<img src="http://127.0.0.1:8000/uploads/user_avatars/user1/avatar1.jpg">
I tried to do it in several ways, and found one working option:
<img src="../../../uploads/user_avatars/user1/avatar1.jpg" />
Surprisingly, if I try to construct the same path using Vue, nothing loads:
<img :src="getAvatarURL" />
There the "getAvatarURL" function simply returns the string above:
getAvatarURL(){
return "../../../uploads/user_avatars/user1/avatar1.jpg"
At the same time, the only working option, where I manually entered the path to the file, apparently uploads it to the front-end server and only then displays it, because as I noticed in chrome devTools, the path to the file changes to this:
<img src="http://127.0.0.1:8080/img/avatar1.0cb5eef6.jpg" />
I absolutely lost in this. I've tried to change vue config file to change folder where to store images, but it also didn't help.
Please, tell me how to use the link provided from the database correctly?
This going to boil down to how you have your build tools set up, and how you are storing your images.
Maybe not store the full path, but a file name, and have the path be something like public/assets/images/ + filename.ext
Here is how I have my setup. I use Webpack to compile:
webpack.config.js
module.exports = {
entry: { ... },
module: {
rules: [
{
test: /\.(png|jpe?g|gif|bmp)$/i,
type: 'asset/resource'
generator: {
filename: './assets/images/[name][ext]
}
}
]
}
}
Then inside my src file i keep my images in a folder called assets/images. which when compile copies them to public/assets/images.
Then inside my Vue files i can import the file
<script lang="ts">
import { defineComponent, ref } from "vue"
import avatar from '#/assets/images/avatar1.png'
export default defineComponent({
name: 'sidebar-user',
setup() {
return { avatar }
}
})
</script>
and return it to template where it looks like this:
<template>
<img :src="avatar" alt="avatar" />
</template>

EmberJS: How to load assets relative to rootURL or load assets using absolute path

this might be a pretty common question but what I found on google does not help me.
I have a emberJs Project with all assets(images, etc) in
my-ember-project/public/assets/images/
everything works fine when i load the assets from homepage which is the root URL "/" or localhost:4200
for example in my homepage
I have a component with img tag which looks like this
<img src="assets/images/articles/article-1.jpg"/>
on another page with url localhost:4200**/articles/** I also load the same image with the same tag
but from what I've seen it tried to load the image from localhost:4200/articles/assets/images/articles/article-1.jpg and not from the correct path localhost:4200/assets/images/articles/article-1.jpg
adding "/" before "assets/images/" works for me if I'm trying to host my project on root folder
but when I need to host my project on subdirectory so my url (www.mydomain.com/ember-project-here/)
how do I load my assets from absolute path or relative to my settings of rootURL
adding {{rootURL}} seems to do nothing to me
It seems, {{rootURL}} does not work in hbs files (long time ago I used to think it does).
{{env 'rootURL'}} should work, where env is a helper defined like this:
import { get } from '#ember/object';
import { helper } from '#ember/component/helper';
import ENV from 'project-name/config/environment';
export default helper(function([path]) {
return get(ENV, path);
});
you can add a path helper:
import { helper } from '#ember/component/helper';
import ENV from 'project-name/config/environment';
export default helper(function([path]) {
return path.replace(/^~\//, ENV.rootURL);
});
The you can do:
<img src={{path "~/assets/images/articles/article-1.jpg"}} />
This is nice because you can also use variables:
<img src={{path this.myPath}} />
and myPath:
get myPath() {
return `~/assets/images/${this.args.iconName}.jpg`;
}
You've done a good research on this front. Yes, rootURL is the one you want to add to your project since you are deploying your application to a subfolder.
rootURL can be added to any Ember app using the config/environment.js file.
// config/environment.js
module.exports = function(environment) {
var ENV = {
// other configs...
rootURL: '/ember-project-here/',
};
}
The official guide can give you some additional info!

How to build a list of links to html files in Gulp?

How can you use Gulp to gather in one html file a list of all the pages that are in the directory?
For example, in the build directory I have two files contact.html with title "Contacts" and faq.html with the title "Frequently asked questions", I need to get them and create a ui.html which would be a list of links to files of the form:
Frequently asked questions
Contacts
Well, with the addition of step your design (a connected css file).
Found the gulp-listing module, but it can not be customized, there it is as follows:
gulp.task('scripts', function() {
return gulp.src('./src/*.html')
.pipe(listing('listing.html'))
.pipe(gulp.dest('./src/'));
});
I used two gulp modules for do this.
gulp-filelist - for create file list
gulp-modify-file - for update this file
gulp
.src(['./html/**/*.html'])
.pipe(require('gulp-filelist')('filelist.js', { relative: true }))
.pipe(require('gulp-modify-file')((content) => {
const start = 'var list = '
return `${start}${content}`
}))
.pipe(gulp.dest('js'))
After run gulp, you got in js/filelist.js something like this:
var list = [
"Cancellation/template.html",
"Cancellation/email.html",
]
You can add this script in your html file, and with js display all info.

Stylesheet not loaded because of MIME-type Angular application

I'm Working on a Angular 6.x application where i'm trying to change theme (dynamically).
The CLI compile everything properly but in developer console im getting this error message.
Refused to apply style from
'http://localhost:4200/vendor/theme-light.css' because its MIME type
('text/html') is not a supported stylesheet MIME type, and strict MIME
checking is enabled.
My file structure looks like this, the path is correct
project
|-src
|-vendor
|-theme-light.css
|theme-dark.css
My theme changing code looks this
import { Component, Inject, PLATFORM_ID } from '#angular/core';
import { DOCUMENT, isPlatformBrowser } from '#angular/common';
#Component({
..
..
})
linkRef: HTMLLinkElement;
themes = [
{ name: 'Light', href: '../vendor/theme-light.css' },
{ name: 'Dark', href: '../vendor/theme-dark.css' }
];
constructor(#Inject(DOCUMENT) private document: Document, #Inject(PLATFORM_ID) private platformId: Object) {
if (isPlatformBrowser(this.platformId)) {
let theme = this.themes[0];
try {
const stored = localStorage.getItem('theme');
if (stored) {
theme = JSON.parse(stored);
}
} catch (e) {
}
this.linkRef = this.document.createElement('link');
this.linkRef.rel = 'stylesheet';
this.linkRef.href = theme.href;
this.document.querySelector('head').appendChild(this.linkRef);
}
}
setTheme(theme) {
localStorage.setItem('theme', JSON.stringify(theme));
this.linkRef.href = theme.href;
}
Now, I don't really understand why this happens. Is am i missing something ? Feel free to ask for more details if needed.
Any help will be really appreciated.
Thanks
Looks like the href is wrong.
There is a good answer to a different question exactly like yours:
The usual reason for this error message is that when the browser tries to load that resource, the server returns an HTML page instead, for example if your router catches unknown paths and displays a default page without a 404 error. Of course that means the path does not return the expected CSS file / image / icon / whatever...
The solution is to find the correct path and router configuration so that you get your plain CSS file / image / etc. when accessing that path.
In your case it's the css href.
Finally figured out Im giving the wrong path on my path configuration href: '../vendor/theme-light.css' thats returns http://localhost:4200/vendor/theme-light.css on the browser which is not the correct path.
Solution
themes = [
//added the missing src ( source root)
{ name: 'Light', href: '../src/vendor/theme-light.css' },
{ name: 'Dark', href: '../src/vendor/theme-dark.css' }
];
Thank You for your answers
when you're using a static folder , please make sure to use "/" . Let's say for example assets is our static folder , we want the image folder which is under the assets , so you type this src="image/img1.png" , that's wrong you have to add "/" ,,, so it will be like this src="/image/img1.png"
Found this answer here Proper solution
The issue could be with a CSS library starting with comments. While on dev, We do not minify files and We don't remove comments, this meant that the stylesheet started with some comments, causing it to be seen as something different from css.
Removing the library and putting it into vendor file (which is ALWAYS minified without comments) solved the issue.
you have to change the place of your file css into the directory assets assets/style.css
and then put these path in your file index.html src/index.html
<link rel="stylesheet" type="text/css" href="assets/style.css" />
in addition you have to modify to file angular.json in styles
"styles": [
"src/assets/style.css",
"./node_modules/materialize-css/dist/css/materialize.min.css",
],

The right way of setting <a href=""> when it's a local file

I'm trying to link to a local file. I've set href as follows:
Link Anchor
In Firefox, when I right click and "open link in new tab", nothing happens.
When I right click and "copy link location", then manually open a new tab and paste the copied link, it works fine. So it seems my file:// syntax is fine. I've also tried it with 3 slashes like file:/// but it's the same result.
What am I doing wrong?
By definition, file: URLs are system-dependent, and they have little use. A URL as in your example works when used locally, i.e. the linking page itself is in the user’s computer. But browsers generally refuse to follow file: links on a page that it has fetched with the HTTP protocol, so that the page's own URL is an http: URL. When you click on such a link, nothing happens. The purpose is presumably security: to prevent a remote page from accessing files in the visitor’s computer. (I think this feature was first implemented in Mozilla, then copied to other browsers.)
So if you work with HTML documents in your computer, the file: URLs should work, though there are system-dependent issues in their syntax (how you write path names and file names in such a URL).
If you really need to work with an HTML document on your computers and another HTML document on a web server, the way to make links work is to use the local file as primary and, if needed, use client-side scripting to fetch the document from the server,
Organize your files in hierarchical directories and then just use relative paths.
Demo:
HTML (index.html)
<a href='inner/file.html'>link</a>
Directory structure:
base/
base/index.html
base/inner/file.html
....
The href value inside the base tag will become your reference point for all your relative paths and thus override your current directory path value otherwise - the '~' is the root of your site
<head>
<base href="~/" />
</head>
This can happen when you are running IIS and you run the html page through it, then the Local file system will not be accessible.
To make your link work locally the run the calling html page directly from file browser not visual studio F5 or IIS simply click it to open from the file system, and make sure you are using the link like this:
Intro
../htmlfilename with .html
User can do this
This will solve your problem of redirection to anypage for local files.
Try swapping your colon : for a bar |. that should do it
Link Anchor
The right way of setting a href=“” when it's a local file.
It will not make any issue when code or file is online.
FAQ
Hope it will help you.
Here is the alternative way to download local file by client side and server side effort:
<a onclick='fileClick(this)' href="file://C:/path/to/file/file.html"/>
Js:
function fileClick(a) {
var linkTag = a.href;
var substring = "file:///";
if (linkTag.includes(substring)) {
var url = '/cnm/document/v/downloadLocalfile?path=' + encodeURIComponent(linkTag);
fileOpen(url);
}
else {
window.open(linkTag, '_blank');
}
}
function fileOpen(url) {
$.ajax({
url: url,
complete: function (jqxhr, txt_status) {
console.log("Complete: [ " + txt_status + " ] " + jqxhr);
if (txt_status == 'success') {
window.open(url, '_self');
}
else {
alert("File not found[404]!");
}
// }
}
});
}
Server side[java]:
#GetMapping("/v/downloadLocalfile")
public void downloadLocalfile(#RequestParam String path, HttpServletResponse
response) throws IOException, JRException {
try {
String nPath = path.replace("file:///", "").trim();
File file = new File(nPath);
String fileName = file.getName();
response.setHeader("Content-Disposition", "attachment;filename=" +
fileName);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
response.setStatus(200);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
// out.flush();
in.close();
out.close();
}
else {
response.setStatus(404);
}
} catch (Exception ex) {
logger.error(ex.getLocalizedMessage());
}
return;
}