JavaScript實現將圖片地址轉成文件流并上傳
寫在開頭
最近,小編在業(yè)務中遇到一個圖片轉存的場景。
領導:大概過程就是,接口會給我返回一個圖片列表數據,圖片路徑是全路徑,但是路徑中的域名是其他系統(tǒng)的,必須要在用戶選擇圖片的時候將圖片重新轉存到自個的系統(tǒng)上,防止其他系統(tǒng)刪除圖片對此有影響。
我:Em...很合理的需求。
(但是,和有什么關系?我只是一個前端小菜雞呀,不祥的預感.......)
我:(卑微提問)這個過程不是放后端做比較合理一點?
后端大哥:前端不能做?
我:可以可以,只是...這個好像會跨域?
后端大哥:已經配置了請求頭('Access-Control-Allow-Origin': '*'
)。
我:哦,好的,我去弄一下。(*******此處省略幾萬字心理活動內容)
第一種(推薦)
那么,迫于......不,我自愿的,我們來看看前端要如何完成這個轉成過程,代碼比較簡單,直接貼上來瞧瞧:
async function imageToStorage(path) { // 獲取文件名 const startIndex = path.lastIndexOf('/'); const endIndex = path.indexOf('?'); const imgName = path.substring(startIndex + 1, endIndex); // 獲取圖片的文件流對象 const file = await getImgToFile(path, imgName); // TODO: 將File對象上傳到其他接口中 } /** * @name 通過fetch請求文件,將文件轉成文件流對象 * @param { string } path 文件路徑全路徑 * @param { string } fileName 文件名 * @returns { File | undefined } */ function getImgToFile(path, fileName) { const response = await fetch(path); if (response) { const blob = await response.blob(); const file = new File([blob], fileName, { type: blob.type }); return file; } }
上述方式,在后端配置了允許跨域后,正常是沒有什么問題的,也是比較好的一種方式了。
但是,在小編實際第一次編碼測試后,卻還是遇上了跨域。
一猜應該就是后端實際還沒配置好,問了一下。
后端大哥:還沒部署,一會再自己試試。
我:嗯嗯。
第二種
等待的過程,小編又在網上找了找了,找到了第二種方式,各位看官可以瞧瞧:
/** @name 將圖片的網絡鏈接轉成base64 **/ function imageUrlToBase64(imageUrl: string, fileName: string): Promise<File> { return new Promise(resolve => { const image = new Image(); // 讓Image元素啟用cors來處理跨源請求 image.setAttribute('crossOrigin', 'anonymous'); image.src = imageUrl + '&v=' + Math.random(); image.onload = () => { const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const context = canvas.getContext('2d')!; context.drawImage(image, 0, 0, image.width, image.height); // canvas.toDataURL const imageBase64 = canvas.toDataURL('image/jpeg', 1); // 第二個參數是壓縮質量 // 將圖片的base64轉成文件流 const file = base64ToFile(imageBase64, fileName); resolve(file); }; }); } /** @name 將圖片的base64轉成文件流 **/ function base64ToFile(base64: string, fileName: string) { const baseArray = base64.split(','); // 獲取類型與后綴名 const mime = baseArray[0].match(/:(.*?);/)![1]; const suffix = mime.split('/')[1]; // 轉換數據 const bstr = atob(baseArray[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } // 生成文件流 const file = new File([u8arr], `${fileName}.${suffix}`, { type: mime, }); return file; }
這第二種方式由于要先把圖片繪制到 canvas
再去轉成 base64
再去轉成文件流,小編用 console.time
稍微測了一下,每次轉化過程都要幾百毫秒,圖片越大時間越長,挺影響性能的。
所以,小編還是推薦使用第一種方式,當然,最穩(wěn)妥的方案是后端去搞最好了。
網上很多都說第二種方式可以直接繞過跨域,各種談論。
主要就是這個 crossOrigin
屬性。MDN解釋
它原理是通過了 CORS
或者可以再看看這個解釋:傳送門
到此這篇關于JavaScript實現將圖片地址轉成文件流并上傳的文章就介紹到這了,更多相關JavaScript圖片地址轉文件流內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!