1. 程式人生 > >ReactNative 圖片上傳儲存 CameraRoll的使用

ReactNative 圖片上傳儲存 CameraRoll的使用

本文主要介紹CaremaRoll的使用(儲存圖片,獲取手機圖片) 圖片上傳(常用於上傳頭像功能)

CaremaRoll介紹

結合官方文件做說明:

CameraRoll模組提供了訪問本地相簿的功能。在iOS上使用這個模組之前,你需要先連結RCTCameraRoll庫,具體做法請參考連結原生庫文件。

譯註:本模組只提供了基本的訪問圖片的功能,並沒有提供相簿介面。對於多數開發者來說,可能第三方的react-native-image-crop-picker的功能更為完整易用(可多選、壓縮、裁剪等)。

iOS 10的許可權要求

從iOS10開始,訪問相簿需要使用者授權。你需要在Info.plist中新增一條名為NSPhotoLibraryUsageDescription的鍵,然後在其值中填寫向用戶請求許可權的具體描述。編輯完成後這個鍵在Xcode中實際會顯示為Privacy - Photo Library Usage Description。

iOS 11的許可權要求

從iOS11開始,如果您的專案有儲存圖片需求,需要額外申請使用者授權。你需要在Info.plist中新增一條名為NSPhotoLibraryAddUsageDescription的鍵,然後在其值中填寫向用戶請求許可權的具體描述。編輯完成後這個鍵在Xcode中實際會顯示為Privacy - Photo Library Additions Usage Description。而名為NSPhotoLibraryUsageDescription的鍵此時僅控制相簿的讀取。具體說明請翻閱官方文件搜尋相關鍵值。

我們可以看到,一共有兩個許可權需要宣告, 一個是讀取相簿,一個是儲存圖片.
雖然有第三方,但我想自己用基礎的API來實現這個功能 , 也能讓以後對這方面的東西接觸的時候有更好的理解.

然後看一下API:

static saveToCameraRoll(tag, type?)

(1)儲存一個圖片到相簿。
(2)@param {string} tag

在安卓上,本引數是一個本地URI,例如”file:///sdcard/img.png”.
在iOS裝置上可能是以下之一:

  • 本地URI
  • 資源庫的標籤
  • 非以上兩種型別,表示圖片資料將會儲存在記憶體中(並且在本程序持續的時候一直會佔用記憶體),
  • tag 可以是 url、assets-library、記憶體圖片中的一種。

(3)引數 type 不是必須的,可選值是’photo’ 或 ‘video’。用來表示存的是圖片還是視訊。不指定的話程式也會根據字尾自行判斷。(結尾為 .mov 或 .mp4 為視訊,其它為圖片)

返回一個Promise,操作成功時返回新的URI。

static getPhotos(params: object)

把圖片或視訊儲存到相簿中。
返回一個帶有圖片識別符號物件的Promise。返回的物件的結構參見getPhotosReturnChecker。

params:物件 一些篩選的規則 有4個成員變數

1.first 數值 希望獲取多少張圖片的資訊

2.groupTypes 字串 預設為SavedPhotos [Album All Event Faces Library PhotoStream] 僅支援IOS平臺 用來指定獲取圖片或視訊的型別

3.assetType 字串 預設為Photos 表示只獲取圖片 [All Videos]

4.after 字串 用來記錄上一次獲取圖片的結束標誌 方便可以接著上次的位置繼續獲取 它的值不能由開發者隨意賦予,而是應當在上一次獲取圖片後儲存其值。通常,在Android平臺,一開始就給這個值為null,但是在IOS平臺,設定為null會拋一個無法捕捉的異常,導致紅屏。

{
first: 5, 
groupTypes: 'All', 
assetType: 'Photos',
//after:null
}

返回一個Promise,操作成功時返回符合getPhotosReturnChecker結構的物件。
我再後臺打印出來的資料

介紹一下使用方法

儲存圖片

    saveImg(img) {
        let promise = CameraRoll.saveToCameraRoll(img);
        promise.then(function (result) {
            alert('儲存成功!地址如下:\n' + result);
        }).catch(function (error) {
            alert('儲存失敗!\n' + error);
        });
    }

也可以直接寫一句程式碼:

 CameraRoll.saveToCameraRoll(img).then(result => {
            alert('儲存成功!地址如下:\n' + result);
        }).catch(error => {
            alert('儲存失敗!\n' + error);
        })

這裡的引數img 傳來的是一個圖片地址 :

let imgURL = "https://ss1.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=8d3a9ea62c7f9e2f6f351b082f31e962/500fd9f9d72a6059099ccd5a2334349b023bbae5.jpg"

讀取相簿

這裡我拆分成了兩個方法, 一個方法是獲取promise物件, 第二個方法是對這個promise進行分析,拿出我需要的資料.
先看第一個方法 , 前面先不用看, 中間是定義已下param引數, 最後是執行方法,拿到promise.
然後把這個promise給方法2進行分析,取資料.

    //獲取圖片列表
    getImages() {
        if (this.state.nomore) {
            alert('沒有更多圖片了');
            return
        }
        let param = {first: 5, groupTypes: 'All', assetType: 'Photos'};
        // 如果不是第一次取圖片,則this.state.lastCursor不為空,下一次取圖片時就從上次的結尾開始取
        if (this.state.lastCursor) {
            param.after = this.state.lastCursor;
        }

        CameraRoll.getPhotos(param).then(data => {
            console.log(data)
            this._appendAssets(data); // 取到圖片資料後,交由appendAssets處理
        }, (e) => {
        }).done();
    }

這裡,我先遍歷了一下data.edges ,這是一個圖片資訊的陣列, node.image.uri是圖片的uri地址 , 上面圖片的資料就是我這裡得到的 . 遍歷拿到這個uri就可以了.
data.page_info.has_next_page 這個是判斷是否還有沒載入的圖片, 有就是true/沒有未載入的就是false.
如果我們需要分頁載入之類的功能 這個就派上用場了,也是我第一個方法中用來判斷是否有更多圖片的引數.
data.page_info.end_cursor 是這次獲取到的所有圖片裡最後一個圖片的uri , 我們下次再去讀相簿,就可以從這個開始載入了. 可以實現分頁功能 .

    _appendAssets(data) {
        let newState = {};
        let edges = data.edges;
        let photos = [];
        for (let i in edges) {
            photos.push(edges[i].node.image.uri);
        }
        console.log(photos)
        if (!data.page_info.has_next_page) { //已經到相簿的末尾了
            newState.noMore = true;
        }
        if (photos.length > 0) { //如果此次載入的圖片數量大於0
            newState.lastCursor = data.page_info.end_cursor;
            newState.photos = this.state.photos.concat(photos);
            this.setState(newState)
        }

    }

獲取到的相簿圖片用list來展示.
距離底部0.1的時候就去嘗試獲取相簿圖片, 每次獲取5張, 直到全部載入完成. 這裡的0.1是比例,不是px.

<FlatList
                    data={this.state.photos}
                    renderItem={({item}) =>
                        <TouchableOpacity onPress={() => this.setState({
                            img: item
                        })}>
                            <Image
                                source={{uri: item}}
                                style={{width: 250, height: 250, resizeMode: 'stretch'}}/>
                        </TouchableOpacity>}
                    onEndReachedThreshold={0.1}
                    onEndReached={() => this.getImages()}
                />

上傳圖片

首先要有後臺 我這裡沒有 所以就沒有實現這個功能, 但是程式碼是完成了的.
uri 就是圖片的uri, 跟我們前面的一樣. token 是用來鑑別使用者的.
裡面還有個引數url 是後臺接收圖片的地址
這個應該比較好理解了.

    upLoadImg(uri, token) {
        let imgFile = new FromData();
        imgFile.append('file', {uri, type: 'application/octet-stream', name: 'head.jpg'})
        fetch('url', {
            method: 'POST', headers: {
                'Content-Type': 'multipart/form-data;charset=utf-8',
                "x-access-token": token,
            },
            body: imgFile,
        }).then()
    }

最後放上原始碼:

'use strict';
import React, {Component} from 'react';
import {
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
    CameraRoll,
    Image,
    FlatList
} from 'react-native';

//網路圖片地址
let imgURL = "https://ss1.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=8d3a9ea62c7f9e2f6f351b082f31e962/500fd9f9d72a6059099ccd5a2334349b023bbae5.jpg"

export default class Appme extends Component {

    //建構函式
    constructor(props) {
        super(props);
        this.state = {
            photos: [],
            lastCursor: '',
            nomore: false
        };
    }

    componentDidMount() {
        this.getImages();
    }

    render() {

        let data = [{title: 'a'}, {title: 'a'}, {title: 'a'}, {title: 'a'},];
        return (
            <View style={styles.container}>
                <View style={styles.image}>
                    <Image style={styles.img}
                           source={{uri: this.state.img}}
                           resizeMode="contain"/>
                </View>
                <View>
                    <Text onPress={this.saveImg.bind(this, imgURL)} style={[styles.saveImg]}>
                        儲存圖片到相簿
                    </Text>
                </View>
                <View>
                    <Text onPress={() => this.getImages()} style={[styles.saveImg]}>
                        獲取圖片列表
                    </Text>
                </View>

                <FlatList
                    data={this.state.photos}
                    renderItem={({item}) =>
                        <TouchableOpacity onPress={() => this.setState({
                            img: item
                        })}>
                            <Image
                                source={{uri: item}}
                                style={{width: 250, height: 250, resizeMode: 'stretch'}}/>
                        </TouchableOpacity>}
                    onEndReachedThreshold={0.1}
                    onEndReached={() => this.getImages()}
                />
            </View>
        )
    }


    //儲存圖片
    saveImg(img) {
        var promise = CameraRoll.saveToCameraRoll(img);
        promise.then(function (result) {
            alert('儲存成功!地址如下:\n' + result);
        }).catch(function (error) {
            alert('儲存失敗!\n' + error);
        });

        CameraRoll.saveToCameraRoll(img).then(result => {
            alert('儲存成功!地址如下:\n' + result);
        }).catch(error => {
            alert('儲存失敗!\n' + error);
        })
    }


    //獲取圖片列表
    getImages() {
        if (this.state.nomore) {
            alert('沒有更多圖片了');
            return
        }
        let param = {first: 5, groupTypes: 'All', assetType: 'Photos'};
        // 如果不是第一次取圖片,則this.state.lastCursor不為空,下一次取圖片時就從上次的結尾開始取
        if (this.state.lastCursor) {
            param.after = this.state.lastCursor;
        }

        CameraRoll.getPhotos(param).then(data => {
            console.log(data)
            this._appendAssets(data); // 取到圖片資料後,交由appendAssets處理
        }, (e) => {
        }).done();
    }

    _appendAssets(data) {
        let newState = {};
        let edges = data.edges;
        let photos = [];
        for (let i in edges) {
            photos.push(edges[i].node.image.uri);
        }
        console.log(photos)
        if (!data.page_info.has_next_page) { //已經到相簿的末尾了
            newState.noMore = true;
        }
        if (photos.length > 0) { //如果此次載入的圖片數量大於0
            newState.lastCursor = data.page_info.end_cursor;
            newState.photos = this.state.photos.concat(photos);
            this.setState(newState)
        }

    }

    upLoadImg(uri, token) {
        let imgFile = new FromData();
        imgFile.append('file', {uri, type: 'application/octet-stream', name: 'head.jpg'})
        fetch('url', {
            method: 'POST', headers: {
                'Content-Type': 'multipart/form-data;charset=utf-8',
                "x-access-token": token,
            },
            body: imgFile,
        }).then()
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1,
        // justifyContent: 'center',
        backgroundColor: 'white',
        // alignItems: 'center'
    },
    welcome: {
        marginTop: 20,
        fontSize: 20,
    },
    image: {
        borderWidth: 1,
        width: 300,
        height: 100,
        borderRadius: 5,
        borderColor: '#ccc',
        marginTop: 50
    },
    img: {
        height: 98,
        width: 300,
        resizeMode: 'stretch'
    },
    saveImg: {
        height: 30,
        padding: 6,
        textAlign: 'center',
        backgroundColor: '#3BC1FF',
        color: '#FFF',
        marginTop: 10,
    }
});

本文僅提供思路 所以 有點醜…
就不放UI圖了

相關推薦

ReactNative 圖片儲存 CameraRoll的使用

本文主要介紹CaremaRoll的使用(儲存圖片,獲取手機圖片) 圖片上傳(常用於上傳頭像功能) CaremaRoll介紹 結合官方文件做說明: CameraRoll模組提供了訪問本地相簿的功能。在iOS上使用這個模組之前,你需要先連結RCTCam

Nuxt.js vue-quill-editor 圖片 儲存

1. 安裝vue-quill-editor (Git地址) npm install vue-quill-editor --save   2. 在Nuxt.js框架中配置 plugins資料夾中新建:vue-quill-editor.js import Vue from 'v

終於搞定使用node.js +redis 作為服務端,提供圖片儲存服務

系統不提供業務層面上的邏輯,只負責儲存和結構關係。業務相關的資料,全部通過引數化傳入。 upload.js 檔案程式碼: //自定義引數區 var basePath='e:/';//上傳的根路徑 var tempPath='c:/'; var redis_ip='127.0

UEditor圖片儲存位置的修改(JSP)

本人使用的是UEditor1.4.3.3的JSP版本,因為百度開發團隊對Jsp版本後端操作進行了修改,導致現在無法通過json設定將UEditor上傳的圖片儲存到WEB應用外,所以,只能通過對JAR包的反編譯,已達成我們的目標。 我們可以從controller

將本地圖片儲存到資料庫(理論支援各種檔案的

//取得檔案的具體大小 int doclen = this.File1.PostedFile.ContentLength; //設定快取的具體大小 byte[] docB

副文字編輯器 KindEditor 實現圖片到騰訊雲物件儲存 COS

目錄   一、主要功能實現 二、效果圖 三、需要匯入的包 四、前端程式設計 五、後臺程式設計 六、github 下載 附加內容: 一、主要功能實現 1、配置 KindEditor  2、在 KindEditor 中實現圖片上傳

微信公眾號 IOS多圖片儲存一張

wx.chooseImage({ count:imgCount, needResult: 1, sizeType:['original', 'compressed'], sourceType:['album', 'camera'], success:function(res){ ShowOKbt(false

5行程式碼實現微信小程式圖片與騰訊免費5G儲存空間的使用

本文介紹瞭如何在微信小程式開發中使用騰訊官方提供的雲開發功能快速實現圖片的上傳與儲存,以及介紹雲開發的 5G 儲存空間的基本使用方法,這將大大提高微信小程式的開發效率,同時也是微信小程式系列教程的視訊版更新的文字版本摘要。 此文為 「60 節實戰課微信小程式開發視訊教程」 的第 51 小節

阿里雲伺服器 雲物件儲存OOS(二) ---圖片與讀取demo

上一篇講解了無需程式碼操作的阿里OOS雲物件儲存 http://blog.csdn.net/u014520797/article/details/53945912 1、SDK下載,不下載也可以,文章最後有demo,demo裡面有jar包 https://help.aliyun.com/d

跨域獲取圖片並自行儲存

跨域獲取圖片並自行上傳儲存 涉及點: 跨域 CORS 協議 為什麼使用cors,不使用jsonp?因為cors更強大,方便安全,還不需要修改大量的前後端資料格式,只需修改伺服器配置引數,與請求引數。 想要跨域獲取資料與資源,必須由對方伺服器開啟

PHP圖片同時儲存路徑到資料庫

本片文件記載如何將圖片上傳至自己制定的目錄檔案下,同時可以將資訊填入資料庫。本片文件部分技術內容參照w3school。 首先是HTML頁面: <form action="register.php" method="post" enctype="multipart/form-data" onSu

TCP客戶端圖片服務端儲存本地示例

//TCP客戶端public class TCPClient { public static void main(String[] args)throws IOException { Socket socket = new Socket("127.0.0.1",8888)

Asp.Net Core Web Api圖片(一)整合MongoDB儲存例項教程

Asp.Net Core Web Api圖片上傳及MongoDB儲存例項教程(一) 圖片或者檔案上傳相信大家在開發中應該都會用到吧,有的時候還要對圖片生成縮圖。那麼如何在Asp.Net Core Web Api實現圖片上傳儲存以及生成縮圖呢?今天我就使用MongoDB作為圖片儲存,然後使用SixLabors

java Ueditor 百度編輯器 整合ssm後臺多圖片,無縫加入專案做新增儲存

效果圖  多圖片單圖片 上傳到後臺 本地儲存。編輯框回顯,複製貼上直接用,適合實際專案中做 內容發表,發表文章等等編輯自定義上傳圖片 多圖片到後臺路徑,看了網上一推教程,走了很多彎路,簡單明瞭 ,複製貼上直接用 專案地址 https://download.csdn.net/d

記錄 呼叫微信圖片 前端 後端Java下載儲存(多圖

測試頁面 <template>     <div id="test">         <button @click="wxchoose">微信上傳測試</butt

微擎怎麼將編輯器裡的圖片到遠端儲存

背景:前提自己沒有做過介面,全部用微擎的七牛雲自己的遠端附件函式file_remote_upload函式,用的微信藉口上傳圖片,然後過去她的mediaid再用函式就可以了。但是我現在再做編輯器,所以編輯器一旦有圖片就很麻煩,所以我就嘗試先上傳到本地,再在本地用那個函式上傳到七牛雲端儲存。可是,貌似這

富文字編輯器WangEditor,實現圖片OSS雲端儲存

首先,下載WangEditor外掛,下載地址:https://github.com/wangfupeng1988/wangEditor/releases,下載最新的就好了,使用文件地址:第二步,解壓檔案

物件儲存oss整合到thinkPHP,將圖片到oss裡面

阿里雲的物件儲存oss,類似七牛儲存。 前幾天有客戶需要把圖片放在阿里雲的oss裡面,百度過一些資料,好像都是oss比較舊的版本1.幾的,現在上傳一個比較新的oss版本v2.0.5,並整合到think

《React-Native系列》26、 ReactNative實現圖片功能

在檢視ReactNative的官方文件的時候,你會發現其實Fackbook是沒有提供圖片上傳功能的。如果我們的專案裡需要使用圖片上傳(用JS 實現圖片上傳),那我們有沒有什麼辦法呢?解決方案:利用FormData物件,你可以使用一系列的鍵值對來模擬一個完整的表單,然後使用XM

thinkPHP實現物件儲存oss,將圖片到阿里雲oss

演示效果和下載地址:http://www.erdangjiade.com/js/1021.html 可以在阿里雲網站下載oss的demo原始碼PHP版:v2.0.5 https://help.aliyun.com/document_detail/32174.html?sp