├── .gitattributes ├── .gitignore ├── README.md ├── index.js ├── package-lock.json └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-cloudinary-unsigned 2 | 3 | ![Cloudinary Logo](https://res.cloudinary.com/cloudinary/image/upload/b_rgb:ffffff,c_scale,w_500/v1/logo/for_white_bg/cloudinary_logo_for_white_bg.png) 4 | 5 | This module helps you to send files to [Cloudinary](https://cloudinary.com) through an [upload profile](https://cloudinary.com/console/settings/upload). 6 | 7 | Do you like this library? Let me a star! ⭐️👍 8 | 9 | ## Getting started 10 | 11 | `$ npm install react-native-cloudinary-unsigned --save` 12 | 13 | ## Usage 14 | 15 | ```javascript 16 | // Import library into your project 17 | import RNCloudinaryUnsigned from "react-native-cloudinary-unsigned"; 18 | 19 | // Declare your credentials 20 | const CLOUDINARY_CLOUD_NAME = "xxxxxx"; 21 | const CLOUDINARY_UPLOAD_PROFILE_NAME = "xxxxxx"; 22 | RNCloudinaryUnsigned.init(CLOUDINARY_CLOUD_NAME, CLOUDINARY_UPLOAD_PROFILE_NAME) 23 | .then(res => console.log(res)) 24 | .catch(err => console.error(err)); 25 | 26 | // Call function to upload or remove image 27 | export default class App extends Component { 28 | // Upload an image 29 | uploadImage = file => { 30 | RNCloudinaryUnsigned.upload(file) 31 | .then(res => console.log(res)) 32 | .catch(err => console.error(err)); 33 | }; 34 | // Delete an image 35 | deleteImage = token => { 36 | RNCloudinaryUnsigned.delete(token) 37 | .then(res => console.log(res)) 38 | .catch(err => console.error(err)); 39 | }; 40 | } 41 | ``` 42 | 43 | ## API 44 | 45 | ### `upload(filepath: string, filename?: string): Promise` 46 | 47 | Upload the file to Cloudinary using at least `filepath` parameter. 48 | 49 | It could be useful to add the `filename` optional parameter that will act as a prefix to final file name. In your preset parameters, you might set `Use filename` and `Unique filename` to `Yes`. 50 | 51 | ![preset](https://preview.ibb.co/b0CTZ7/preset.png) 52 | 53 | ### `delete(token: string): Promise` 54 | 55 | Delete the uploaded file using the `delete_token` returned in the upload response. After 10 minutes has passed, the image cannot be deleted from the client side. 56 | 57 | ## How safe / secure is it to use unsigned upload from mobile clients? 58 | 59 | The only "risk" in using unsigned uploads with Cloudinary is the possibility that another person will view the source code of your uploader, replicate the configuration and issue uploads from another place onto your account. 60 | 61 | However, the following is worth mentioning: 62 | 63 | * This will "only" allow them to initiate unsigned-uploads to your account (may result with a certain Storage/Transformations quotas abuse). 64 | * This will NOT allow anyone to Delete / Edit / Overwrite any of your existing content on the account. A list of supported unsigned-upload options is available here. 65 | * As a safety measure, from time to time, you may want to change your upload-preset's name (can be done via the account settings) to reduce the possibility of someone using your configuration without your permission. 66 | * Finally we must say that until the writing of these lines we haven't heard of anyone of our customers experiencing this kind of offense. 67 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import fileType from "react-native-file-type"; 3 | 4 | const API_END_POINT = "https://api.cloudinary.com/v1_1/"; 5 | 6 | const CLOUD_NAME = null; 7 | const UPLOAD_PROFILE_NAME = null; 8 | 9 | class RNCloudinaryUnsigned { 10 | init = (a, b) => { 11 | return new Promise((resolve, reject) => { 12 | if (a && b) { 13 | CLOUD_NAME = a; 14 | UPLOAD_PROFILE_NAME = b; 15 | console.log("ok"); 16 | resolve({ 17 | error: false, 18 | credentials: { 19 | CLOUD_NAME, 20 | UPLOAD_PROFILE_NAME 21 | } 22 | }); 23 | } else { 24 | reject( 25 | "Credentials must not be empty. Please check your configuration." 26 | ); 27 | } 28 | }); 29 | }; 30 | upload = (file, filename = null) => { 31 | return new Promise((resolve, reject) => { 32 | if (CLOUD_NAME && UPLOAD_PROFILE_NAME) { 33 | if (file) { 34 | fileType(file).then(type => { 35 | const url = `${API_END_POINT}${CLOUD_NAME}/image/upload`; 36 | const fd = new FormData(); 37 | const name = filename 38 | ? `${filename}.${type.ext}` 39 | : `upload.${type.ext}`; 40 | fd.append("upload_preset", UPLOAD_PROFILE_NAME); 41 | fd.append("file", { 42 | name, 43 | uri: file, 44 | type: type.mime 45 | }); 46 | const config = { 47 | headers: { 48 | "Content-Type": "multipart/form-data" 49 | } 50 | }; 51 | axios 52 | .post(url, fd, config) 53 | .then(res => { 54 | resolve(res); 55 | }) 56 | .catch(err => { 57 | reject(err); 58 | }); 59 | }); 60 | } else { 61 | reject("You must send a file path to the function."); 62 | } 63 | } else { 64 | reject( 65 | "Credentials must not be empty. Please check your configuration." 66 | ); 67 | } 68 | }); 69 | }; 70 | delete = token => { 71 | if (CLOUD_NAME && UPLOAD_PROFILE_NAME) { 72 | if (token) { 73 | return new Promise((resolve, reject) => { 74 | const url = `${API_END_POINT}${CLOUD_NAME}/delete_by_token`; 75 | axios 76 | .post(url, { token }) 77 | .then(res => { 78 | resolve(res); 79 | }) 80 | .catch(err => { 81 | reject(err); 82 | }); 83 | }); 84 | } else { 85 | reject("You must send a token to the function."); 86 | } 87 | } 88 | }; 89 | } 90 | 91 | module.exports = new RNCloudinaryUnsigned(); 92 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-cloudinary-unsigned", 3 | "version": "1.0.6", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "axios": { 8 | "version": "git+https://github.com/axios/axios.git#0b3db5d87a60a1ad8b0dce9669dbc10483ec33da", 9 | "requires": { 10 | "follow-redirects": "1.4.1", 11 | "is-buffer": "2.0.2" 12 | } 13 | }, 14 | "debug": { 15 | "version": "3.1.0", 16 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 17 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 18 | "requires": { 19 | "ms": "2.0.0" 20 | } 21 | }, 22 | "follow-redirects": { 23 | "version": "1.4.1", 24 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", 25 | "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", 26 | "requires": { 27 | "debug": "3.1.0" 28 | } 29 | }, 30 | "is-buffer": { 31 | "version": "2.0.2", 32 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.2.tgz", 33 | "integrity": "sha512-imvkm8cOGKeZ/NwkAd+FAURi0hsL9gr3kvdi0r3MnqChcOdPaQRIOQiOU+sD40XzUIe6nFmSHYtQjbkDvaQbEg==" 34 | }, 35 | "ms": { 36 | "version": "2.0.0", 37 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 38 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-cloudinary-unsigned", 3 | "version": "1.0.6", 4 | "description": "Upload/delete images to/from Cloudinary (unsigned upload) using React Native.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "react-native", 11 | "cloudinary" 12 | ], 13 | "author": "Xavier Colombel", 14 | "license": "", 15 | "peerDependencies": { 16 | "react-native": "^0.41.2" 17 | }, 18 | "dependencies": { 19 | "axios": "git+https://github.com/axios/axios.git", 20 | "react-native-file-type": "git+https://github.com/prscX/react-native-file-type.git" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/XavierColombel/react-native-cloudinary-unsigned" 25 | } 26 | } 27 | --------------------------------------------------------------------------------