凌峰创科服务平台

Android上传图片到PHP服务器,如何实现?

  1. Android 端:

    Android上传图片到PHP服务器,如何实现?-图1
    (图片来源网络,侵删)
    • 用户从相册或相机选择一张图片。
    • 将图片文件转换成 byte[]Base64 字符串。
    • 使用 HttpURLConnection 或第三方库(如 OkHttp)构建一个 POST 请求。
    • 将图片数据作为 multipart/form-data 格式发送到 PHP 服务器。
  2. PHP 服务器端:

    • 接收来自 Android 的 POST 请求。
    • 检查请求中是否包含文件。
    • 验证文件类型(是否为图片)、文件大小等。
    • 为上传的文件生成一个唯一的文件名,以防止文件名冲突。
    • 将文件从临时目录移动到你指定的服务器目标目录。
    • 返回一个 JSON 响应,告知客户端上传成功或失败。

第一步:Android 客户端实现

我们将使用 HttpURLConnection 和现代的 java.nio.file API 来实现,这种方式不依赖第三方库,适合初学者理解原理。

添加网络权限

app/manifests/AndroidManifest.xml 文件中,必须添加网络访问权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 添加网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 如果需要从相机拍照,还需要相机权限 -->
    <uses-permission android:name="android.permission.CAMERA" />
    <!-- 如果需要从相册选择,需要存储权限 (Android 13+ 需要 READ_MEDIA_IMAGES) -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
    <application ...>
        ...
    </application>
</manifest>

创建上传工具类 UploadUtil.java

这个类将封装所有上传逻辑。

Android上传图片到PHP服务器,如何实现?-图2
(图片来源网络,侵删)
import android.util.Log;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class UploadUtil {
    private static final String TAG = "UploadUtil";
    private static final String LINE_END = "\r\n";
    private static final String TWO_HYPHENS = "--";
    private static final String BOUNDARY = "----WebKitFormBoundary7MA4YWxkTrZu0gW"; // 分隔符
    public static void uploadFile(String filePath, String fileField, String serverUrl, final UploadCallback callback) {
        File file = new File(filePath);
        if (!file.exists()) {
            if (callback != null) callback.onFailure("文件不存在");
            return;
        }
        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            URL url = new URL(serverUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            // 创建输出流
            outputStream = new DataOutputStream(connection.getOutputStream());
            // 1. 添加文件头信息
            StringBuilder sbHeader = new StringBuilder();
            sbHeader.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
            sbHeader.append("Content-Disposition: form-data; name=\"" + fileField + "\"; filename=\"" + file.getName() + "\"" + LINE_END);
            sbHeader.append("Content-Type: application/octet-stream" + LINE_END); // 可以根据文件类型修改,如 image/jpeg
            sbHeader.append(LINE_END);
            outputStream.write(sbHeader.toString().getBytes("UTF-8"));
            // 2. 添加文件内容
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            fileInputStream.close();
            // 3. 混结束标记
            outputStream.writeBytes(LINE_END);
            outputStream.writeBytes(TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + LINE_END);
            // 获取服务器响应码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取服务器返回的数据
                inputStream = connection.getInputStream();
                StringBuilder response = new StringBuilder();
                byte[] buffer2 = new byte[1024];
                int bytesRead2;
                while ((bytesRead2 = inputStream.read(buffer2)) != -1) {
                    response.append(new String(buffer2, 0, bytesRead2));
                }
                if (callback != null) callback.onSuccess(response.toString());
            } else {
                String errorMsg = "上传失败,服务器响应码: " + responseCode;
                Log.e(TAG, errorMsg);
                if (callback != null) callback.onFailure(errorMsg);
            }
        } catch (IOException e) {
            Log.e(TAG, "上传IO异常: " + e.getMessage());
            if (callback != null) callback.onFailure("上传IO异常: " + e.getMessage());
        } finally {
            // 关闭流和连接
            try {
                if (outputStream != null) outputStream.close();
                if (inputStream != null) inputStream.close();
                if (connection != null) connection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    // 上传回调接口
    public interface UploadCallback {
        void onSuccess(String response);
        void onFailure(String error);
    }
}

在 Activity 或 Fragment 中调用

假设你有一个按钮,点击后选择图片并上传。

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
    private static final int PICK_IMAGE_REQUEST = 1;
    private static final int REQUEST_PERMISSION_CODE = 1001;
    private Button uploadButton;
    private String selectedFilePath;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        uploadButton = findViewById(R.id.btn_upload);
        uploadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 检查权限
                if (checkPermission()) {
                    chooseImage();
                } else {
                    requestPermission();
                }
            }
        });
    }
    private void chooseImage() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "选择图片"), PICK_IMAGE_REQUEST);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            Uri filePathUri = data.getData();
            selectedFilePath = getRealPathFromURI(filePathUri); // 获取真实路径
            if (selectedFilePath != null) {
                Toast.makeText(this, "已选择: " + selectedFilePath, Toast.LENGTH_SHORT).show();
                // 开始上传
                startUpload();
            }
        }
    }
    private void startUpload() {
        // 服务器地址
        String serverUrl = "http://你的服务器地址/upload.php";
        // 文件字段名,必须和PHP $_FILES['image'] 中的 'image' 对应
        String fileField = "image";
        Toast.makeText(this, "开始上传...", Toast.LENGTH_SHORT).show();
        UploadUtil.uploadFile(selectedFilePath, fileField, serverUrl, new UploadUtil.UploadCallback() {
            @Override
            public void onSuccess(String response) {
                runOnUiThread(() -> {
                    Log.d("Upload", "服务器响应: " + response);
                    Toast.makeText(MainActivity.this, "上传成功: " + response, Toast.LENGTH_LONG).show();
                });
            }
            @Override
            public void onFailure(String error) {
                runOnUiThread(() -> {
                    Log.e("Upload", "上传失败: " + error);
                    Toast.makeText(MainActivity.this, "上传失败: " + error, Toast.LENGTH_LONG).show();
                });
            }
        });
    }
    // 获取文件真实路径 (方法可能需要根据Android版本调整)
    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new Cursor
Android上传图片到PHP服务器,如何实现?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇