0

I want to mention that the image file is changing continuously. I'm using the middleware of NodeJS:

app.use("/image.jpg",express.static(_dirname+"/image.jpg")

The problem is that the Node conveys the image.jpg without really telling that the file has been modified. Pressing a button this part will occur.

var image=new Image();
image.onload=function(){rendering to canvas}
image.src="/image.jpg";

Somehow there is a problem...

The server's picture file gets modified then it emits to the client to draw the image, regarding to the results, the client is rendering the first image it has loaded again, although the image on the url has been changed. I think the client is caching the image? and thinks that the image is unmodified so it keeps using it. Is there a way to draw the current image on the url? Are there even better methods?

killertoge
  • 333
  • 1
  • 3
  • 11

1 Answers1

1

You can use the fetch() API to implement cache-busting without cluttering your client's browser cache with a bunch of /image.jpg?bust=... resources.

After deciding on a folder in your server that you want to allow static access to changing files (this is preferable to the pattern where you allowed static access to a single file), you can implement your real-time updates using fs.watch() like so:

Node app.js (with express 3/4):

const fs = require('fs')
const path = require('path')
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server)

server.listen(process.env.PORT || 8080)

app.use('/', express.static(path.resolve(__dirname, './watched-directory')))

//...

io.on('connection', (socket) => {
  //...
});

fs.watch('watched-directory', {
  //don't want watch process hanging if server is closed
  persistent: false,
  //supported on Windows OS / Mac OSX
  recursive: true,
}, (eventType, filename) => {
  if (eventType === 'change') {
    io.emit('filechange', filename)
  }
})

Browser index.html:

<script src="/socket.io/socket.io.js"></script>
<script>
  let socket = io.connect()

  socket.on('filechange', async (filename) => {
    console.log(filename)

    let response = await fetch(filename, { cache: 'no-store' })
    let blob = await response.toBlob()
    let url = URL.createObjectURL(blob)

    //modified from your question
    let image = new Image()
    image.addEventListener('load', () => {
      //your canvas rendering code here
    })
    image.src = url
  })
</script>
Patrick Roberts
  • 40,065
  • 5
  • 74
  • 116
  • ()=> = function(), let, await, async are new for me .-. I will study your code! – killertoge Jul 20 '17 at 16:41
  • @OnlyMyRailgun At least in this case, [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) is effectively the same thing as `var`, but for the others, [`() => {}`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), and [`async/await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function), is just syntactic sugar in ES2017 for dealing with [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises), which the `fetch()` API uses. – Patrick Roberts Jul 20 '17 at 16:44