当前位置:首页 > 行业动态 > 正文

安卓向服务器传图片

安卓向服务器传图片需申请存储权限,将Bitmap转为Base64或Multipart格式,通过OkHttp/Retrofit发起POST请求,建议开子线程处理网络操作, 服务器端需配置跨域及文件接收

安卓向服务器传输图片的实现步骤


权限配置

  1. AndroidManifest.xml 声明权限

    • 网络权限:android.permission.INTERNET
    • 读写存储权限(Android 10以下需动态申请):
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. 动态申请运行时权限(Android 6.0+)

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
    }

图片处理

  1. 获取图片路径

    • 从相册选择:使用 Intent.ACTION_GET_CONTENT 或第三方库(如 PhotoPicker)。
    • 从相机获取:保存图片到指定路径,并通过 FileProvider 处理 Android 7.0+ 的文件共享限制。
  2. 图片压缩

    安卓向服务器传图片  第1张

    • 使用 Bitmap 压缩减少体积:
      Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); // 质量设为80%
      byte[] imageBytes = baos.toByteArray();
    • 或使用第三方库(如 Luban)进行无损压缩。
  3. 处理图片旋转(可选)

    • 读取图片的 EXIF 信息,校正方向:
      int rotation = getExifRotation(imagePath);
      matrix.postRotate(rotation);
      Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);

上传图片到服务器

  1. 使用 OkHttp 或 Retrofit 发送 Multipart 请求

    • OkHttp 示例
      OkHttpClient client = new OkHttpClient();
      MultipartBody body = new MultipartBody.Builder()
          .setType(MultipartBody.FORM)
          .addFormDataPart("file", "image.jpg", 
              RequestBody.create(imageBytes, MediaType.parse("image/jpeg")))
          .build();
      Request request = new Request.Builder()
          .url("https://yourserver.com/upload")
          .post(body)
          .build();
      client.newCall(request).enqueue(new Callback() {
          @Override public void onFailure(Call call, IOException e) { / 处理失败 / }
          @Override public void onResponse(Call call, Response response) throws IOException { / 处理成功 / }
      });
    • Retrofit 示例
      @Multipart
      @POST("upload")
      Call<ResponseBody> uploadImage(@Part MultipartBody.Part image);
  2. 异步处理与进度监听

    • 使用 AsyncTask(已过时)或 LiveData/Coroutine 实现异步上传,避免阻塞主线程。
    • 通过 ProgressRequestBody 监听上传进度并更新 UI。

服务器端接口要求

  1. 接收 Multipart 数据

    • 后端需解析 Content-Type: multipart/form-data,提取文件流并保存。
    • 示例(Node.js):
      const multer = require('multer');
      const upload = multer({ dest: 'uploads/' });
      app.post('/upload', upload.single('file'), (req, res) => {
          res.json({ path: req.file.path });
      });
  2. 安全性校验

    • 限制文件类型(如仅允许 image/jpeg)。
    • 校验文件大小,防止反面上传。

常见问题与解决方案

问题 解决方案
文件过大导致上传失败 前端压缩图片,或后端分片上传(如断点续传)。
Android 10+ 存储权限受限 使用 MediaStore API 或 Scoped Storage 模式,避免直接访问文件路径。
图片方向错误 通过 EXIFInterface 读取旋转信息并修正 Bitmap
网络不稳定导致上传失败 添加重试机制,或使用 WorkManager 实现后台可靠上传。

相关问题与解答

问题1:如何优化图片上传的速度?

  • 解答
    1. 压缩图片:降低分辨率或使用 WebP 格式(比 JPEG 更小)。
    2. 分片上传:将图片分割为多个小块并行上传,支持断点续传。
    3. 启用 GZIP:服务器端开启 GZIP 压缩,减少传输数据量。
    4. CDN 加速:将图片存储至 CDN 节点,提升全球访问速度。

问题2:如何在应用退出后仍能上传图片?

  • 解答
    使用 WorkManager 实现后台任务:

    WorkRequest uploadWork = new OneTimeWorkRequest.Builder(UploadWorker.class)
        .setInputData(new Data.Builder().putString("filePath", imagePath).build())
        .build();
    WorkManager.getInstance(context).enqueue(uploadWork);

    UploadWorker 需继承 Worker 类,在 doWork() 中执行上传逻辑

0