diff --git a/package.json b/package.json
index 3172b628..825b5ed8 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,9 @@
     "vue-ls": "^3.2.1",
     "vue-router": "^3.1.6",
     "vuejs-logger": "^1.5.3",
-    "vuex": "^3.1.1"
+    "vuex": "^3.1.1",
+    "flv.js": "^1.5.0",
+    "vue-contextmenujs": "^1.3.9"
   },
   "devDependencies": {
     "@babel/polyfill": "^7.4.4",
diff --git a/src/main.js b/src/main.js
index 17d9f0f4..7cabec64 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2,6 +2,7 @@ import '@babel/polyfill'
 import Vue from 'vue'
 import App from './App.vue'
 import router from './router'
+import Contextmenu from 'vue-contextmenujs'
 import store from './store/'
 import './logger'
 
@@ -15,6 +16,7 @@ Vue.config.productionTip = false
 Vue.prototype.VERSION = version
 
 Vue.use(router)
+Vue.use(Contextmenu)
 
 new Vue({
   router,
diff --git a/src/views/attachment/AttachmentList.vue b/src/views/attachment/AttachmentList.vue
index 03c30139..67218240 100644
--- a/src/views/attachment/AttachmentList.vue
+++ b/src/views/attachment/AttachmentList.vue
@@ -132,6 +132,7 @@
               :bodyStyle="{ padding: 0 }"
               hoverable
               @click="handleShowDetailDrawer(item)"
+              @contextmenu.prevent="handleContextMenu($event, item)"
             >
               <div class="attach-thumb">
                 <span v-show="!handleJudgeMediaType(item)">当前格式不支持预览</span>
@@ -298,6 +299,46 @@ export default {
         this.drawerVisible = true
       }
     },
+    handleContextMenu(event, item) {
+      this.$contextmenu({
+        items: [
+          {
+            label: '复制图片链接',
+            onClick: () => {
+              const text = `${encodeURI(item.path)}`
+              this.$copyText(text)
+                .then(message => {
+                  this.$log.debug('copy', message)
+                  this.$message.success('复制成功!')
+                })
+                .catch(err => {
+                  this.$log.debug('copy.err', err)
+                  this.$message.error('复制失败!')
+                })
+            },
+            divided: true
+          },
+          {
+            label: '复制 Markdown 格式链接',
+            onClick: () => {
+              const text = `![${item.name}](${encodeURI(item.path)})`
+              this.$copyText(text)
+                .then(message => {
+                  this.$log.debug('copy', message)
+                  this.$message.success('复制成功!')
+                })
+                .catch(err => {
+                  this.$log.debug('copy.err', err)
+                  this.$message.error('复制失败!')
+                })
+            }
+          }
+        ],
+        event,
+        minWidth: 210
+      })
+      return false
+    },
     handlePaginationChange(page, size) {
       this.$log.debug(`Current: ${page}, PageSize: ${size}`)
       this.pagination.page = page
diff --git a/src/views/attachment/components/AttachmentDrawer.vue b/src/views/attachment/components/AttachmentDrawer.vue
index c1ebd80f..e1bb1f70 100644
--- a/src/views/attachment/components/AttachmentDrawer.vue
+++ b/src/views/attachment/components/AttachmentDrawer.vue
@@ -37,6 +37,7 @@
               v-for="(item, index) in formattedDatas"
               :key="index"
               @click="handleShowDetailDrawer(item)"
+              @contextmenu.prevent="handleContextMenu($event, item)"
             >
               <span v-show="!handleJudgeMediaType(item)">当前格式不支持预览</span>
               <img
@@ -165,6 +166,47 @@ export default {
       this.$log.debug('Show detail of', attachment)
       this.detailVisible = true
     },
+    handleContextMenu(event, item) {
+      this.$contextmenu({
+        items: [
+          {
+            label: '复制图片链接',
+            onClick: () => {
+              const text = `${encodeURI(item.path)}`
+              this.$copyText(text)
+                .then(message => {
+                  this.$log.debug('copy', message)
+                  this.$message.success('复制成功!')
+                })
+                .catch(err => {
+                  this.$log.debug('copy.err', err)
+                  this.$message.error('复制失败!')
+                })
+            },
+            divided: true
+          },
+          {
+            label: '复制 Markdown 格式链接',
+            onClick: () => {
+              const text = `![${item.name}](${encodeURI(item.path)})`
+              this.$copyText(text)
+                .then(message => {
+                  this.$log.debug('copy', message)
+                  this.$message.success('复制成功!')
+                })
+                .catch(err => {
+                  this.$log.debug('copy.err', err)
+                  this.$message.error('复制失败!')
+                })
+            }
+          }
+        ],
+        event,
+        zIndex: 1001,
+        minWidth: 210
+      })
+      return false
+    },
     loadAttachments() {
       this.queryParam.page = this.pagination.page - 1
       this.queryParam.size = this.pagination.size