1. 程式人生 > 程式設計 >JavaScript 禁止使用者儲存圖片的實現程式碼

JavaScript 禁止使用者儲存圖片的實現程式碼

新增事件禁止選擇、拖拽、右鍵(簡單的禁止使用者儲存圖片,但無法阻止使用者開啟控制檯檢視,或是直接抓包)
將之轉換為 canvas(讓瀏覽器認為不是圖片以此禁止使用者對之進行圖片的操作,但無法阻止抓包)
禁止使用者使用控制檯檢視原始碼(阻止瀏覽器開啟控制檯,但無法阻止抓包)
傳輸圖片使用自定義格式(可以阻止抓包,但需要後臺配合)

注:以下內容使用 react+ts 實現

新增事件禁止選擇、拖拽、右鍵

簡而言之,這是一種簡單有效的方式,能夠在使用者不開啟控制檯的情況下阻止使用者儲存圖片。

export function preventDefaultListener(e: any) {
 e.preventDefault()
}

;<img
 src={props.url}
 alt="JavaScript 禁止使用者儲存圖片的實現程式碼"
 style={{
 //禁止使用者選擇
 userSelect: 'none',//禁止所有滑鼠事件,過於強大,圖片僅用於展示可用
 // pointerEvents: 'none',}}
 onTouchStart={preventDefaultListener}
 onContextMenu={preventDefaultListener}
 onDragStart={preventDefaultListener}
/>

參考:https://www.jb51.net/article/185677.htm

將之轉換為 canvas

另一種思路是將圖片轉換為 canvas 避免使用者使用img相關的操作。

將圖片轉成 canvas

export async function imageToCanvas(url: string,canvas: HTMLCanvasElement) {
 return new Promise((resolve,reject) => {
 //新建Image物件,引入當前目錄下的圖片
 const img = new Image()
 img.src = url
 const c = canvas.getContext('2d')!

 //圖片初始化完成後呼叫
 img.onload = function () {
  //將canvas的寬高設定為影象的寬高
  canvas.width = img.width
  canvas.height = img.height

  //canvas畫圖片
  c.drawImage(img,img.width,img.height)
  resolve()
 }
 img.addEventListener('error',(e) => {
  reject(e)
 })
 })
}

禁用 canvas 事件

const throwFn = () => {
 throw new Error(
 "Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.",)
}

const $canvasRef = useRef<HTMLCanvasElement>(null)
 useEffect(() => {
  ;(async () => {
   await imageToCanvas(props.url,$canvasRef.current!)
   $canvasRef.current!.toBlob = throwFn
   $canvasRef.current!.toDataURL = throwFn
  })()
 },[])
 return (
  <canvas
   ref={$canvasRef}
   onTouchStart={preventDefaultListener}
   onContextMenu={preventDefaultListener}
  />
 )

禁止使用者使用控制檯檢視原始碼

如果能禁止使用者操作控制檯,那麼自然能夠避免使用者檢視原始碼了,下面是一個簡單的實現。

/**
 * 相容非同步函式的返回值
 * @param res 返回值
 * @param callback 同步/非同步結果的回撥函式
 * @typeparam T 處理引數的型別,如果是 Promise 型別,則取出其泛型型別
 * @typeparam Param 處理引數具體的型別,如果是 Promise 型別,則指定為原型別
 * @typeparam R 返回值具體的型別,如果是 Promise 型別,則指定為 Promise 型別,否則為原型別
 * @returns 處理後的結果,如果是同步的,則返回結果是同步的,否則為非同步的
 */
export function compatibleAsync<T = any,Param = T | Promise<T>,R = T>(
 res: Param,callback: (r: T) => R,): Param extends Promise<T> ? Promise<R> : R {
 return (res instanceof Promise
 ? res.then(callback)
 : callback(res as any)) as any
}

/**
 * 測試函式的執行時間
 * 注:如果函式返回 Promise,則該函式也會返回 Promise,否則直接返回執行時間
 * @param fn 需要測試的函式
 * @returns 執行的毫秒數
 */
export function timing<R>(
 fn: (...args: any[]) => R,// 函式返回型別是 Promise 的話,則返回 Promise<number>,否則返回 number
): R extends Promise<any> ? Promise<number> : number {
 const begin = performance.now()
 const res = fn()
 return compatibleAsync(res,() => performance.now() - begin)
}
/**
 * 禁止他人除錯網站相關方法的集合物件
 */
export class AntiDebug {
 /**
 * 不停迴圈 debugger 防止有人除錯程式碼
 * @returns 取消函式
 */
 public static cyclingDebugger(): Function {
 const res = setInterval(() => {
  debugger
 },100)
 return () => clearInterval(res)
 }
 /**
 * 檢查是否正在 debugger 並呼叫回撥函式
 * @param fn 回撥函式,預設為過載頁面
 * @returns 取消函式
 */
 public static checkDebug(
 fn: Function = () => window.location.reload(),): Function {
 const res = setInterval(() => {
  const diff = timing(() => {
  debugger
  })
  if (diff > 500) {
  console.log(diff)
  fn()
  }
 },1000)
 return () => clearInterval(res)
 }
}
useEffect(() => {
 const cancel1 = AntiDebug.cyclingDebugger() as any
 const cancel2 = AntiDebug.checkDebug(() =>
 console.log('請不要開啟除錯'),) as any
 return () => {
 cancel1()
 cancel2()
 }
},[])

return <img src={url} alt="JavaScript 禁止使用者儲存圖片的實現程式碼" />

傳輸圖片使用自定義格式

該功能需要服務端配合,故而此處贊不實現,可以參考微信讀書,就是將文字轉為 canvas,資料傳輸也進行了加密,可以在很大程度上防止普通使用者想要複製/下載的行為了。

到此這篇關於JavaScript 禁止使用者儲存圖片的文章就介紹到這了,更多相關js 禁止儲存圖片內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!