The react android capacitor app interrupts the file upload to the http server

I created a native Android application from react in javascript using a capacitor, but it cannot upload files from the mobile application to the server, meaning it starts downloading and stops immediately, but without errors, while everything works in the web version of the application. in the web markup code of the main page, I use the file loader from the ant design library. I have provided different permissions in the Android manifest and for webview in the MainActivity code.java didn't help anything

{/* The button for adding files */}
  <Upload
    action={${process.env.REACT_APP_API_URL}/api/Photo?event_id=${event.id}}
    listType="picture-card"
    showUploadList={false}
    multiple={true}
    onChange={handleUploadChange(event.id)} // Handler for changing the download status
  >
    <button style={{ border: 0, background: "none" }} type="button">
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>Add Files</div>
    </button>
  </Upload>
    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:largeHeap="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true"
        android:requestLegacyExternalStorage="true">

        <activity
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"
            android:name=".MainActivity"
            android:label="@string/title_activity_main"
            android:theme="@style/AppTheme.NoActionBarLaunch"
            android:launchMode="singleTask"
            android:exported="true">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
    </application>

    <!-- Permissions -->
</manifest>
import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.memory.com',
  appName: 'My TimeLines',
  webDir: 'build',

  server: {
    androidScheme: 'http',
  },
  android: {
    allowMixedContent: true,
    webContentsDebuggingEnabled: true,
  },
  plugins: {
    CapacitorHttp: {
      enabled: true,
    },
    CapacitorCookies: {
      enabled: true,
    },
  },
};

export default config;

Upvotes: 0

Views: 39

Answers (1)

I found a solution, I had to write my own file downloader for fetch requests, because the capacitor blocks XMLhttp requests and put it in upload as a custom method:

const handleCustomRequest = async ({ file, onSuccess, onError }, eventId) => {
console.log("Sending the file manually:", file);

if (!eventId) {
  console.error("Error: EventId is missing");
  onError(new Error("Error: eventId is missing"));
  return;
}

const formData = new FormData();

// Force the file name to be encoded in UTF-8
const encodedFileName = new Blob([file], { type: file.type });

formData.append("file", encodedFileName, encodeURIComponent(file.name)); // Encoding the file name

try {
  const response = await fetch(
    `${process.env.REACT_APP_API_URL}/api/Photo?event_id=${eventId}`,
    {
      method: "POST",
      body: formData,
    }
  );

  if (!response.ok) throw new Error(`Error: ${response.statusText}`);

  console.log("The file has been uploaded successfully!");
  onSuccess();
} catch (error) {
  console.error("Error when uploading a file:", error);
  onError(error);
}

};

<Upload
    customRequest={(options) => handleCustomRequest(options, event.id)}
    listType="picture-card"
    showUploadList={false}
    multiple={true}
    onChange={handleUploadChange(event.id)} // Handler for changing the download status
  >
    <button style={{ border: 0, background: "none" }} type="button">
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>Add Files</div>
    </button>
  </Upload>

Upvotes: 0

Related Questions