PhilippKrone / react-native-fileupload

Multi-form file upload for react-native
MIT License
158 stars 74 forks source link

App crashes when trying a POST #3

Closed BigPun86 closed 8 years ago

BigPun86 commented 8 years ago

I am trying to upload a image from FileSystem, which is jpg Format. But i get the RedBox Message "could not invoke FileUpload.upload"

screen shot 2015-12-14 at 19 11 24

This is my code:

var FileUpload = require('NativeModules').FileUpload;
var UIImagePickerManager = require('NativeModules').UIImagePickerManager;
    UIImagePickerManager.showImagePicker(options, (didCancel, response) => {
        console.log('Response = ', response);
        if (didCancel) {
            console.log('User cancelled image picker');
        }
        else {
            fileName = response.uri.substring(response.uri.lastIndexOf("/") + 1);
            fsPath = response.uri;
            var binaryResponse = response.data;
            const obj = {
                uploadUrl: API_URL + 'user/avatar',
                method: 'POST',
                headers: {
                    'Authorization': AuthStore.getUserTokenWithBearer()
                },
                fields: {
                    'hello': 'world',
                },
                files: [{
                    filename: 'image',            // this is what your server is looking for
                    filepath: response.uri,     // uri from response (local path of image on device)
                    filetype: 'image/jpeg'
                }]
            };
            FileUpload.upload(obj, (err, result) => {
                console.log('upload:', err, result);
            });
        }
    });

Any ideas?

BigPun86 commented 8 years ago

Crashlytics reports me that it crashes at following line:

FileUploadModule.java line 84 in com.yoloci.fileupload.FileUploadModule.upload

        // set headers
        ReadableMapKeySeyIterator iterator = headers.keySetIterator();
        while (iterator.hasNextKey()) {
            String key = iterator.nextKey();
            connection.setRequestProperty(key, headers.getString(key));
        }
PhilippKrone commented 8 years ago

Hi,

this is due to a breaking change in RN.. they renamed "ReadableMapKeySeyIterator" to "ReadableMapKeySetIterator" and I've not just updated the code to reflect this breaking change.

Regards Philipp

BigPun86 commented 8 years ago

Okay thanks. So just renaming it won´t solve the issue?

PhilippKrone commented 8 years ago

I think it should. :) This is what I'm currently using internally.

            // set headers
            ReadableMapKeySetIterator iterator = headers.keySetIterator();
            while (iterator.hasNextKey()) {
                String key = iterator.nextKey();
                connection.setRequestProperty(key, headers.getString(key));
            }

There might be 2-3 places where you have to rename it. :)

BigPun86 commented 8 years ago

Won´t work for me :(

![Uploading Screen Shot 2015-12-15 at 09.39.30.png…]()

PhilippKrone commented 8 years ago

Can you give this code a try? Thats what I'm using without issues atm.

package com.yoloci.fileupload;

import android.os.Bundle;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

import java.io.DataInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.DataOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.facebook.react.bridge.WritableMap;
import java.io.FileInputStream;

import org.json.JSONObject;

public class FileUploadModule extends ReactContextBaseJavaModule {

    @Override
    public String getName() {
        return "FileUpload";
    }

    public FileUploadModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @ReactMethod
    public void upload(final ReadableMap options, final Callback callback) {
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary =  "*****";

        String uploadUrl = options.getString("uploadUrl");
        String method;
        if (options.hasKey("method")) {
            method = options.getString("method");
        } else {
            method = "POST";
        }

        ReadableMap headers = options.getMap("headers");
        ReadableArray files = options.getArray("files");
        ReadableMap fields = options.getMap("fields");

        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;
        DataInputStream inputStream = null;
        URL connectURL = null;
        FileInputStream fileInputStream = null;

        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1*1024*1024;

        try {

            connectURL = new URL(uploadUrl);

            connection = (HttpURLConnection) connectURL.openConnection();

            // Allow Inputs & Outputs.
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            connection.setRequestMethod(method);

            // set headers
            ReadableMapKeySetIterator iterator = headers.keySetIterator();
            while (iterator.hasNextKey()) {
                String key = iterator.nextKey();
                connection.setRequestProperty(key, headers.getString(key));
            }

            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);

            outputStream = new DataOutputStream( connection.getOutputStream() );

            // set fields
            ReadableMapKeySetIterator fieldIterator = fields.keySetIterator();
            while (fieldIterator.hasNextKey()) {
                outputStream.writeBytes(twoHyphens + boundary + lineEnd);

                String key = fieldIterator.nextKey();
                outputStream.writeBytes("Content-Disposition: form-data; name=\"" + key +  "\"" + lineEnd + lineEnd);
                outputStream.writeBytes(fields.getString(key));
                outputStream.writeBytes(lineEnd);
            }

            for (int i = 0; i < files.size(); i++) {

                ReadableMap file = files.getMap(i);
                String filename = file.getString("filename");
                String filepath = file.getString("filepath");
                filepath = filepath.replace("file://", "");
                fileInputStream = new FileInputStream(filepath);

                outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                outputStream.writeBytes("Content-Disposition: form-data; name=\"image\";filename=\"" + filename + "\"" + lineEnd);
                outputStream.writeBytes(lineEnd);

                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                buffer = new byte[bufferSize];

                // Read file
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {
                    outputStream.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }

                outputStream.writeBytes(lineEnd);
            }

            outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

            // Responses from the server (code and message)

            int serverResponseCode = connection.getResponseCode();
            String serverResponseMessage = connection.getResponseMessage();
            if (serverResponseCode != 200) {
                fileInputStream.close();
                outputStream.flush();
                outputStream.close();
                callback.invoke("Error happened: " + serverResponseMessage, null);
            } else {
                BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                br.close();
                JSONObject mainObject = new JSONObject(sb.toString());
                if (mainObject != null) {
                    BundleJSONConverter bjc = new BundleJSONConverter();
                    Bundle bundle = bjc.convertToBundle(mainObject);
                    WritableMap map = Arguments.fromBundle(bundle);

                    fileInputStream.close();
                    outputStream.flush();
                    outputStream.close();
                    callback.invoke(null, map);
                } else {
                    fileInputStream.close();
                    outputStream.flush();
                    outputStream.close();
                    callback.invoke(null, null);
                }
            }

        } catch(Exception ex) {
            callback.invoke("Error happened: " + ex.getMessage(), null);
        }
    }
}
BigPun86 commented 8 years ago

Thanks for fast reply :) But this is what i get with your code, during build:

/fileupload/FileUploadModule.java:8: error: cannot find symbol import com.facebook.react.bridge.ReadableMapKeySetIterator;
PhilippKrone commented 8 years ago

Can you check whether this exists in your version of RN? It's this file: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMapKeySetIterator.java

BigPun86 commented 8 years ago

It is exact the same code i have...I use RN 0.15

screen shot 2015-12-15 at 09 53 48

PhilippKrone commented 8 years ago

Are you on discord? I'm "PhilippKrone" there - just drop me a line and we can go through in a more reasonable way than here i think :)

BigPun86 commented 8 years ago

Great support mate :)