Задать вопрос
@Chesterfield25

Почему не загружается аудио файл на сервер?

Создаю андроид приложение которое записывает аудио файл и отправляет его на хостинг по определенной ссылке. Файл создается но не получается его отправить на хостнг, выдает ошибку Ответ: {"success":false,"message":"\u0424\u0430\u0439\u043b \u043d\u0435 \u0431\u044b\u043b \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044f."}

Код приложения

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_AUDIO_PERMISSION_CODE = 200;
    private MediaRecorder mediaRecorder;
    private Uri audioUri;
    private Handler handler = new Handler();
    private static final String UPLOAD_URL = "https://site.net/recordingaudio/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Проверка разрешений
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.RECORD_AUDIO}, REQUEST_AUDIO_PERMISSION_CODE);
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                try {
                    startRecording();
                } catch (FileNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    private void startRecording() throws FileNotFoundException {
        if (mediaRecorder != null) {
            stopRecording();
        }

        try {
            audioUri = createAudioFile();
        } catch (IOException e) {
            Log.e("AudioRecorder", "Ошибка создания файла для записи: " + e.getMessage());
            return;
        }

        mediaRecorder = new MediaRecorder();
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        // Устанавливаем URI для MediaRecorder
        mediaRecorder.setOutputFile(getContentResolver().openFileDescriptor(audioUri, "w").getFileDescriptor());

        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
            Log.d("AudioRecorder", "Запись начата");

            handler.postDelayed(stopAndUploadRunnable, 1 * 60 * 1000);
        } catch (IOException e) {
            Log.e("AudioRecorder", "Ошибка записи: " + e.getMessage());
        } catch (IllegalStateException e) {
            Log.e("AudioRecorder", "MediaRecorder находится в недопустимом состоянии: " + e.getMessage());
        }
    }

    private final Runnable stopAndUploadRunnable = new Runnable() {
        @Override
        public void run() {
            stopRecording();
            uploadAudio(audioUri);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                try {
                    startRecording();
                } catch (FileNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    };

    private void stopRecording() {
        if (mediaRecorder != null) {
            try {
                mediaRecorder.stop();
            } catch (RuntimeException stopException) {
                Log.e("AudioRecorder", "Ошибка остановки записи: " + stopException.getMessage());
            } finally {
                mediaRecorder.release();
                mediaRecorder = null;
                Log.d("AudioRecorder", "Запись остановлена");
            }
        }
    }

    private void uploadAudio(Uri fileUri) {
        if (fileUri == null) {
            Log.e("Upload", "URI файла не существует");
            return;
        }

        try {
            byte[] fileData = getFileDataFromUri(fileUri); // Получаем данные в виде байтов

            VolleyMultipartRequest multipartRequest = new VolleyMultipartRequest(Request.Method.POST, UPLOAD_URL,
                    null,
                    new Response.Listener<NetworkResponse>() {
                        @Override
                        public void onResponse(NetworkResponse response) {
                            Log.d("Upload", "Ответ: " + new String(response.data));
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            Log.e("Upload", "Ошибка: " + error.getMessage());
                        }
                    }) {
                @Override
                protected Map<String, DataPart> getByteData() {
                    Map<String, DataPart> params = new HashMap<>();
                    // Используем массив байтов вместо URI
                    params.put("audioFile", new DataPart("recorded_audio.3gp", fileData, "audio/3gp"));
                    return params;
                }
            };

            RequestQueue requestQueue = Volley.newRequestQueue(this);
            requestQueue.add(multipartRequest);
        } catch (IOException e) {
            Log.e("Upload", "Ошибка при чтении файла: " + e.getMessage());
        }
    }

    private byte[] getFileDataFromUri(Uri uri) throws IOException {
        try (InputStream inputStream = getContentResolver().openInputStream(uri);
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            return byteArrayOutputStream.toByteArray();
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.Q)
    private Uri createAudioFile() throws IOException {
        ContentResolver resolver = getContentResolver();
        ContentValues contentValues = new ContentValues();

        // Генерация уникального имени файла на основе текущего времени
        String fileName = "recorded_audio_" + System.currentTimeMillis() + ".3gp";
        contentValues.put(MediaStore.Audio.Media.DISPLAY_NAME, fileName);
        contentValues.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp");
        contentValues.put(MediaStore.Audio.Media.RELATIVE_PATH, Environment.DIRECTORY_MUSIC);

        Uri audioUri = resolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, contentValues);
        if (audioUri == null) {
            throw new IOException("Не удалось создать аудиофайл");
        }

        return audioUri;
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(stopAndUploadRunnable);
        stopRecording();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_AUDIO_PERMISSION_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    try {
                        startRecording();
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
            } else {
                Log.e("Permissions", "Разрешение на запись аудио отклонено");
            }
        }
    }
}


Код серверной части

<?php
// Включаем отображение ошибок для отладки
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Устанавливаем директорию для сохранения загруженных файлов
$targetDir = "uploads/";

// Проверяем, существует ли директория, если нет - создаем
if (!is_dir($targetDir)) {
    mkdir($targetDir, 0755, true);
}

// Подготовка массива для ответа
$response = array('success' => false, 'message' => '');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Проверяем, был ли загружен файл
    if (isset($_FILES['audioFile'])) {
        $file = $_FILES['audioFile'];

        // Проверяем, есть ли ошибки при загрузке
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $response['message'] = "Ошибка загрузки файла: " . $file['error'];
        } else {
            // Перемещаем загруженный файл в целевую директорию
            $targetFile = $targetDir . basename($file['name']);
            if (move_uploaded_file($file['tmp_name'], $targetFile)) {
                $response['success'] = true;
                $response['message'] = "Файл был загружен успешно: " . htmlspecialchars(basename($file['name']));
            } else {
                $response['message'] = "Не удалось загрузить файл.";
            }
        }
    } else {
        $response['message'] = "Файл не был загружен. Проверьте имя поля.";
    }
} else {
    $response['message'] = "Неверный метод запроса.";
}

// Устанавливаем заголовок ответа
header('Content-Type: application/json');
// Возвращаем ответ в формате JSON
echo json_encode($response);
?>
  • Вопрос задан
  • 86 просмотров
Подписаться 1 Простой 3 комментария
Пригласить эксперта
Ответы на вопрос 1
402d
@402d
начинал с бейсика на УКНЦ в 1988
Тут разные подходы к тому как делаются запросы к серверу.
Вы правильно поняли, что нужен класс посредник, который перекодирует в ожидаемый PHP от апача формат.
Но не разобрались с ним до конца.
С моей точке зрения проще на беке подстроиться к тому как java шлет данные.
$data_in = file_get_contents('php://input');
и уже с ними работать. Но это личное мнение, так как на PHP у меня опыта на 15 лет больше чем в яве
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы