上一篇我們對服務端和阿里云oss的配置及前端調用做了簡單的介紹,但是一直報錯。最終判斷是文件格式問題,通常我們在reactnative中用formData上傳,
formData.append('file', {uri: file, name: nameType(type), type: 'multipart/form-data'});
這里的file是文件的本地路徑,如"file://android_asset/文件名",這里注意file://在安卓選擇后并沒有,需要我們來進行添加。但事實證明這里并不能直接通過路徑上傳,而是需要對文件進行處理,轉為二進制數據,我們這里選擇的是'rn-fetch-blob'庫。選擇這個庫的原因有兩個,一是blob比ArrayBuffer存儲的二進制數據更大比較適合不定大小的文件對象,而是我們采用的網絡請求庫 axios或者fetch在請求大文件時不是特別穩定,因此RNFetchBlob.fetch將是更好的選擇。
Blob 與 ArrayBuffer的區別
- Blob和ArrayBuffer都能存儲二進制數據。Blob相對而言儲存的二進制數據大(如File文件對象)。
- ArrayBuffer對象表示原始的二進制數據緩沖區,即在內存中分配指定大小的二進制緩沖區(容器),用于存儲各種類型化數組的數據,是最基礎的原始數據容器,無法直接讀取或寫入, 需要通過具體視圖來讀取或寫入,即TypedArray對象或DataView對象對內存大小進行讀取或寫入;Blob對象表示一個不可變、原始數據的類文件對象。
- ArrayBuffer 是存在內存中的,可以直接操作。而 Blob 可以位于磁盤、高速緩存內存和其他不可用的位置。
?通過比較我們確定了文件格式,那么接下來上代碼。
export const uploadFileToOSS = async (files: Array<string>,type: string,
): Promise<any[]> => {const ossConfig = await globalStore.getOssConfig();let saveFiles: any[] = [];rootStore.globalIndicator.changeStatus(true)for (const fileOne of files) {try {const filePath = `${ossConfig.dir}${Date.now()}_${nameType(type)}`;let fileLength = 0;const fileConfigs = [{ name: 'policy', data: ossConfig.policy },{ name: 'x-oss-signature', data: ossConfig.signature },{ name: 'x-oss-signature-version', data: ossConfig.version },{ name: 'x-oss-credential', data: ossConfig.x_oss_credential },{ name: 'x-oss-date', data: ossConfig.x_oss_date },{ name: 'x-oss-security-token', data: ossConfig.security_token },{ name: 'key', data: filePath },{ name: 'success_action_status', data: '200' },{name: 'file',filename: nameType(type),data: RNFetchBlob.wrap(fileOne)}];const res = await RNFetchBlob.fetch('POST',ossConfig.host,{ 'Content-Type': 'multipart/form-data;' },fileConfigs).uploadProgress((written, total) => {fileLength = total;const progress = Math.round((written / total) * 100);console.log(`已上傳: ${progress}%`);});if (res?.info().status === 200) {const fileName = fileOne.substring(fileOne.lastIndexOf('/') + 1) || nameType(type);const params = {fileDir: ossConfig.dir,fileLength,fileName,filePath,mimeType: mimeType(type)};const result = await globalStore.saveUploadFile(params);console.log("result.data>", result.data);if (result.success) {saveFiles.push(result.data);}}} catch (error) {console.error('上傳失敗:', error);xmToast.fail('上傳失敗,請重試');}}rootStore.globalIndicator.changeStatus(false)return saveFiles;
};
此處強調幾點注意事項:
1、rootStore.globalIndicator.changeStatus(true) 這是我寫的一個全局的加載loading,可直接忽略,用自己的即可。
2、阿里云oss上傳成功后,沒有回調。
我們需要拼接出文件地址,我代碼中是這樣的。
`${ossConfig.host}}${ossConfig.dir}${Date.now()}_${nameType(type)}`
最終是這樣的? http://xmgj2025-test.oss-cn-hongkong.aliyuncs.com/424234324_img.png
3、阿里云oss上傳后的文件地址不能直接打開查看,而是直接下載了 。
這就造成了很大的不便。因此我們通過保存文件到我們的后端,由后端下載后通過我們的服務地址來預覽,這樣便可完美解決不能直接預覽的問題了。
4、代碼中我適配了同時上傳多個文件,用到了循環,切記!!這里需要循環上傳文件到oss,并且在上傳后要掉接口保存文件到后端服務器,for循環不會等待異步完成,與我們的需要不否,因此我采用了for of 進行順序上傳。當然你也可以用map。
好了,通過上面的代碼,我們已經可以順利的上傳文件到阿里云oss服務器了!
歡迎各位猿友提問,如果覺得寫的不錯,請留下你的贊哦!
?
?
?