1. HarmonyOS File和base64字符串轉換
1.1. Base64
1.1.1. Base64認知
??Base64 是一種基于64個 ASCII 字符來表示二進制數據的表示方法,這個64個不同的字符為:
??(1)大、小寫字母(A– Z、a–z)。52個
??(2)數字。(0–9)10個
??(3)兩個特殊字符。(+、/)2個
1.1.2. Base64原理
??(1)將圖片轉換成二進制數據。
??(2)將8比特位為一個單元的字節數據拆分為以6個比特位為一個單元的字節數據。
??(3)將6個比特位為一個單元高位補齊00,補足8個比特。
??(4)如果剩余的字節不足6位,則先低位補00湊齊6位之后,高位再補00,補足8位。
??(5)當未編碼(1中的二進制數據)輸入的長度不是三的倍數時,則編碼輸出(3)必須添加填充,使其長度為四的倍數。填充字符為=
??(6)將補齊8個比特的二進制數據,轉化為10進制數據。然后到上面的base64碼表中進行查詢,并生成字符。
??(7)將所有的字符進行拼接組成base64字符串。
1.1.3. 舉例說明
??比如字符串:“byhk”
??(1)將其轉換為二進制數據:01100010、01111001、01101000、01101011
??(2)將8比特拆為6比特:011000,100111,100101,101000,011010,11
??(3)高位補齊00,補足8個比特:0011000,0100111,00100101,00101000,00011010,00110000,
??(4)最后的11不滿6位,先低位補0000變為:110000,然后高位補00,變為:00110000
??(5)步驟3,最后的數量不是4的倍數,因此需要填充兩個=
??(6)因此"byhk"的base64的結果為:“Ynloaw==”
鴻蒙base64圖片保存到本地沙盒
1.2. 保存base64圖片到本地沙盒
??圖片base64格式
data:image/png;base64,iVBORw0KGg....
1.2.1. 解析圖片數據
private static dealBase64Str(base64Data: string): string {let imageData: stringif (base64Data.startsWith("data")) {const base64Split: string[] = base64Data.split(",")if (base64Split.length !== 2) {throw new Error(`Illegal base64 data`)}imageData = base64Split[1].trim()} else {imageData = base64Data}return imageData
}
1.2.2. 創建沙盒文件
private static createFile(context: Context) {let pathDir = context.filesDirlet fileName = systemDateTime.getTime(true)let filePath = `${pathDir}/${fileName}.jpg`let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)return file
}
1.2.3. 將圖片數據寫入
let bufferImage = buffer.from(base64Result, 'base64')
await fs.write(file.fd, bufferImage.buffer)
fs.closeSync(file.fd)
1.2.4. 完整代碼
export class ImageUtils {static async saveBase64Image(base64ImageData: string, context: Context): Promise<Boolean> {try {let base64Result = ImageUtils.dealBase64Str(base64ImageData)let file = ImageUtils.createFile(context)let bufferImage = buffer.from(base64Result, 'base64')await fs.write(file.fd, bufferImage.buffer)fs.closeSync(file.fd)return Promise.resolve(true)} catch (e) {throw new Error(e)}}private static dealBase64Str(base64Data: string): string {let imageData: stringif (base64Data.startsWith("data")) {const base64Split: string[] = base64Data.split(",")if (base64Split.length !== 2) {throw new Error(`ImageUtils: Illegal base64 data`)}imageData = base64Split[1].trim()} else {imageData = base64Data}return imageData}private static createFile(context: Context) {let pathDir = context.filesDirlet fileName = systemDateTime.getTime(true)let filePath = `${pathDir}/${fileName}.jpg`let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)return file}
}
1.3. 從網頁打開獲取文件,并轉成base64
1.3.1. 鴻蒙原生代碼
import web_webview from '@ohos.web.webview';
import picker from '@ohos.file.picker';
import { BusinessError } from '@ohos.base';
import { fileIo } from '@kit.CoreFileKit';
import util from '@ohos.util';@Entry
@Component
struct UploadFile {controller:web_webview.WebviewController = new web_webview.WebviewController();@State uri: Array<string> | null = null;// // 將 ArrayBuffer 轉換為 Base64 字符串// arrayBufferToBase64(buffer: ArrayBuffer): string {// let binary = '';// const bytes = new Uint8Array(buffer);// for (let i = 0; i < bytes.byteLength; i++) {// binary += String.fromCharCode(bytes[i]);// }// return globalThis.btoa(binary); // 使用 btoa 將二進制數據編碼為 Base64// }//// btoa(binaryData: Uint8Array) {// // 創建一個Base64Helper實例// let base64Helper = new util.Base64Helper();// // 使用Base64Helper將二進制數據轉換為Base64編碼的字符串// return base64Helper.encodeToStringSync(new Uint8Array(binaryData));// }build() {Column(){Text('選中的圖片')List(){ForEach(this.uri,(item:string)=>{ListItem(){Row(){Image(item).width('30vh').height('30vh')}}.width('30vh').height('30vh')})}.width('30vh').height('30vh')Web({src:$rawfile('setAttrAndEvent/uploadFile/index.html'),controller:this.controller}).fileAccess(false).width('100%').height('100vh').backgroundColor('grey').onShowFileSelector((event)=>{console.log('MyFileUploader onShowFileSelector invoked')let PhotoSelectOptions = new picker.PhotoSelectOptions();PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;// PhotoSelectOptions.maxSelectNumber = 5;PhotoSelectOptions.maxSelectNumber = 1;const photoPicker = new picker.PhotoViewPicker();photoPicker .select(PhotoSelectOptions).then(async (photoSelectResult) => {this.uri = photoSelectResult.photoUris;console.info('photoPicker .select to file succeed and photoSelectResult is:' + JSON.stringify(photoSelectResult));console.info('photoPicker .select to file succeed and uri is:' + this.uri);if (this.uri.length > 0) {let oneUri = this.uri[0]// let uri: string = ''; // 這里應該是你的URIlet file = fileIo.openSync(oneUri, fileIo.OpenMode.READ_ONLY);console.info('file fd: ' + file.fd);let stat = await fileIo.stat(file.fd);// let buffer = new ArrayBuffer(4096);console.info('readSync data to file succeed and buffer size is: stat' + stat.size)let buffer = new ArrayBuffer(stat.size);let readLen = fileIo.readSync(file.fd, buffer);console.info('readSync data to file succeed and buffer size is:' + readLen);fileIo.closeSync(file);console.info('readSync data to file succeed and buffer size is: buffer 大小 ' + buffer.byteLength)// 創建一個Base64Helper實例let base64Helper = new util.Base64Helper();// 使用Base64Helper將二進制數據轉換為Base64編碼的字符串let base64Data = base64Helper.encodeToStringSync(new Uint8Array(buffer.slice(0, readLen)));// let base64Data = btoa(String.fromCharCode(...new Uint8Array(buffer.slice(0, readLen-1))));console.info('Base64 encoded data: ' + base64Data);}if (event) {event.result.handleFileList(this.uri);}}).catch((err: BusinessError) => {console.error(`Invoke photoPicker .select failed, code is ${err.code}, message is ${err.message}`);})return true;})}}
}
1.3.2. 關鍵代碼
if (this.uri.length > 0) {let oneUri = this.uri[0]// let uri: string = ''; // 這里應該是你的URIlet file = fileIo.openSync(oneUri, fileIo.OpenMode.READ_ONLY);console.info('file fd: ' + file.fd);let stat = await fileIo.stat(file.fd);// let buffer = new ArrayBuffer(4096);console.info('readSync data to file succeed and buffer size is: stat' + stat.size)let buffer = new ArrayBuffer(stat.size);let readLen = fileIo.readSync(file.fd, buffer);console.info('readSync data to file succeed and buffer size is:' + readLen);fileIo.closeSync(file);console.info('readSync data to file succeed and buffer size is: buffer 大小 ' + buffer.byteLength)// 創建一個Base64Helper實例let base64Helper = new util.Base64Helper();// 使用Base64Helper將二進制數據轉換為Base64編碼的字符串let base64Data = base64Helper.encodeToStringSync(new Uint8Array(buffer.slice(0, readLen)));// let base64Data = btoa(String.fromCharCode(...new Uint8Array(buffer.slice(0, readLen-1))));console.info('Base64 encoded data: ' + base64Data);}
1.3.3. html代碼
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
<div class="upload"><!-- 點擊上傳按鈕 --><form id="upload-form" enctype="multipart/form-data"><input type="file" id="upload" name="upload"/></form>
</div>
</body>
</html>
<style>body{width:100%;height:auto;margin:50px auto;text-align:center;background-color:#2EB3FF}
</style>
1.4. 在線圖片轉為base64字符串
let OutData: http.HttpResponse
http.createHttp().request("https://xxx/xxx.png",//在線圖片地址
(error: BusinessError, data: http.HttpResponse) => {
if (error) {
console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
} else {
OutData = data
let code: http.ResponseCode | number = OutData.responseCode
if (ResponseCode.ResponseCode.OK === code) {
let imageData: ArrayBuffer = OutData.result as ArrayBuffer;
let base64 = new util.Base64Helper(); // 實例化Base64Helper
let data = base64.encodeSync(new Uint8Array(imageData.slice(0, imageData.byteLength))) // 轉換成Uint8Array
console.info(`data長度:${data.length}`)
console.info(`data:${data}`)
let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM : true })
let retStr = textDecoder.decodeWithStream( data , {stream: false}); // 可以把Uint8Array轉碼成base64
}
}
}
)
1.5. 參考文檔
??(1)文件下載上傳:https://developer.huawei.com/consumer/cn/doc/system-Guides/network-exp-file-0000001093424975#section492510893519
??(2)載到公共目錄
在沙箱目錄里,在手機里看不到的。下載到公共目錄可參考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/request-dir-permission
??(3)預覽文件
您可參考previewKit:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/preview-introduction
??(4)Preview Kit的openPreview接口在傳入文件預覽信息時,當前僅支持傳入文件的uri,用戶文件uri介紹參考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/user-file-uri-intro-V5
??(5)打開和保存PDF文檔:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/pdf-open-docunent
??(6)@ohos.file.picker (選擇器):https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-file-fs