Access to dynamic Images with vue and playframework

111 views Asked by At

I use vue and Play!Framework for my project.

Fronted: Vue.js 2.6.12 Backend: Play!Framework with Scala (2.12.8)

I use following Code snippet to upload an image to my server (This is copied from here: https://www.playframework.com/documentation/2.8.x/ScalaFileUpload

  def uploadImage = Action.async{   implicit request =>
         
        request.body.asMultipartFormData.map{ pic =>
            val file = pic.files

           val userIdTemp = pic.asFormUrlEncoded("userId")
           val userId = userIdTemp.head.toInt

           val itemIdTemp = pic.asFormUrlEncoded("itemId")
           val itemId = itemIdTemp.head.toInt

            val contentType = file.head.contentType
            val filename    = Paths.get(file.head.filename).getFileName.toString().toLowerCase()
            val fileSize    = file.head.fileSize
            print("content Type: "+contentType)
            print("filename: "+filename)
            print("filesize: "+fileSize)
            

            file.head.ref.moveFileTo(Paths.get(s"...\\vui\\src\\assets\\"+filename).toFile, replace = true)
           
           
            print("***********************uploadImage -3")
            service.saveImage(userId,itemId, filename.toString()) map{ foundItems =>
                Ok(Json.toJson(foundItems))
            }

        }.getOrElse(null) // change me
    }

I upload the image to the server and save the url related to an item in my database. This works fine. I display the images in my fronted with following code snippet:

<b-carousel-slide  :img-src="require('../../assets/'+img.imgUrl)" >
</b-carousel-slide>

When i try to upload an image which i have uploaded before it works fine, but if i try to upload an image for the first time i get following exception:

Error: Cannot find module './001.jpg'
    webpackContextResolve .*$:70
    webpackContext .*$:65
    render FoodMenuItem.vue:1302
    renderList VueJS
    render FoodMenuItem.vue:1274
    VueJS 14
    createNewImages FoodMenuItem.vue:809
    uploadImage FoodMenuItem.vue:802
    promise callback*p$1.then vue-resource.esm.js:230
    uploadImage FoodMenuItem.vue:799
    onSelect FoodMenuItem.vue:720
    VueJS 33
    updateTarget transporter.js:145
    updated transporter.js:98
    VueJS 13
    click FoodMenuItem.vue:1256
    VueJS 3
vue.runtime.esm.js:1897
    VueJS 17
    createNewImages FoodMenuItem.vue:809
    uploadImage FoodMenuItem.vue:802
    then vue-resource.esm.js:230
    uploadImage FoodMenuItem.vue:799
    onSelect FoodMenuItem.vue:720
    VueJS 33
    updateTarget transporter.js:145
    updated transporter.js:98
    VueJS 13
    click FoodMenuItem.vue:1256
    VueJS 3

The images is uploaded and the url is saved in the database, but my frontend crashed. When i "complete" refresh my browser and try it again, evertything works fine. My guess is, i can not access to image with require who are not loaded?

Is there a way to display this images without refreshing the browser? Is that a normal way to handle images in a web application? Any help will help!

If u need more information to help, just ask me:)

Thank you!

1

There are 1 answers

0
muepsi On

I tried a lot of things and i followed this steps:

https://blog.lichter.io/posts/dynamic-images-vue-nuxt/

As i told you above, i am uploading my images at the moment to the assets folder in UI. If i am in dev mode i can upload new images and show them with following code:

<img :src="require(`../../assets/${img.imgUrl}`)" >

And this works now. But when i change in production mode with:

  1. npm run build
  2. sbt compile stage
  3. sbt start

The Frontend App will be a static app in the folder public/ui/

and then i don“t know the right relative path for the new images...

vue.config.js:

const path = require("path");

const webpack = require('webpack')

module.exports = {
outputDir: path.resolve(__dirname, "../public/ui"),
assetsDir: process.env.NODE_ENV === 'production' ? 'static':'',

devServer: {
    public: 'localhost:8080',
    headers: {
        'Access-Control-Allow-Origin': '*',
    }
},

configureWebpack: {
    plugins: [
        new webpack.DefinePlugin({
            'process.conf': {
                'RECAPTCHA_SITEKEY': JSON.stringify(process.env.RECAPTCHA_SITEKEY)
            }
        })
    ]
},

chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .loader('vue-loader')
      .tap(options => {
        options.transformAssetUrls = {
          img: 'src',
          image: 'xlink:href',
          'b-avatar': 'src',
          'b-img': 'src',
          'b-img-lazy': ['src', 'blank-src'],
          'b-card': 'img-src',
          'b-card-img': 'src',
          'b-card-img-lazy': ['src', 'blank-src'],
          'b-carousel-slide': 'img-src',
          'b-embed': 'src'
        }

        return options
      })
      
  }

}

In which folder do i have upload the images? How can i reach the new uploaded images in production mode?