You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala如何从外部URL获取图片并转换为字节数组?

在Scala中从URL获取图片并转为字节数组的实现方法

首先纠正你代码里的两个小问题:

  1. 方法签名语法错误,正确写法应为 def getImageFromUrlInBytes(url: String): Array[Byte](原写法颠倒了参数列表与返回值的位置)
  2. Scala中字节数组的类型是 Array[Byte],而非 Array[Bytes]

下面提供几种常见的实现方式:

1. 使用Java标准库(无额外依赖)

Java 9+ 简化版本

利用Java 9新增的InputStream.readAllBytes()方法,代码简洁且自动关闭流:

import java.net.URL
import java.io.IOException

def getImageFromUrlInBytes(url: String): Array[Byte] = {
  try {
    new URL(url).openStream().readAllBytes()
  } catch {
    case e: IOException => 
      // 根据业务需求处理异常,此处示例抛出运行时异常
      throw new RuntimeException(s"下载图片失败:${e.getMessage}", e)
  }
}

Java 8及以下兼容版本

手动读取流并管理资源,确保在任何场景下都关闭流:

import java.net.URL
import java.io.{InputStream, ByteArrayOutputStream, IOException}

def getImageFromUrlInBytes(url: String): Array[Byte] = {
  var inputStream: InputStream = null
  val outputStream = new ByteArrayOutputStream()
  
  try {
    inputStream = new URL(url).openStream()
    val buffer = new Array[Byte](1024) // 1KB缓冲区
    var bytesRead = inputStream.read(buffer)
    
    while (bytesRead != -1) {
      outputStream.write(buffer, 0, bytesRead)
      bytesRead = inputStream.read(buffer)
    }
    
    outputStream.toByteArray()
  } catch {
    case e: IOException =>
      throw new RuntimeException(s"下载图片失败:${e.getMessage}", e)
  } finally {
    // 确保资源被释放
    Option(inputStream).foreach(_.close())
    outputStream.close()
  }
}

2. 使用Apache Commons IO库(简化代码)

如果项目已引入Apache Commons IO,可借助工具类大幅简化代码:

先添加sbt依赖:

libraryDependencies += "commons-io" % "commons-io" % "2.15.1"

然后实现方法:

import java.net.URL
import org.apache.commons.io.IOUtils
import java.io.IOException

def getImageFromUrlInBytes(url: String): Array[Byte] = {
  try {
    IOUtils.toByteArray(new URL(url))
  } catch {
    case e: IOException =>
      throw new RuntimeException(s"下载图片失败:${e.getMessage}", e)
  }
}

3. 异步非阻塞实现(基于Akka HTTP)

高并发场景下推荐使用异步方式避免阻塞线程,以下是Akka HTTP示例:

先添加sbt依赖:

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-http" % "10.5.3",
  "com.typesafe.akka" %% "akka-stream" % "2.8.5"
)

然后实现异步方法:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpRequest
import akka.stream.scaladsl.Sink
import scala.concurrent.Future

// 初始化ActorSystem
implicit val system: ActorSystem = ActorSystem("ImageDownloadSystem")
import system.dispatcher

def getImageFromUrlInBytesAsync(url: String): Future[Array[Byte]] = {
  Http().singleRequest(HttpRequest(uri = url))
    .flatMap { response =>
      if (response.status.isSuccess()) {
        // 流式读取响应体并合并为字节数组
        response.entity.dataBytes.runWith(Sink.fold(Array.empty[Byte])(_ ++ _))
      } else {
        Future.failed(new RuntimeException(s"请求失败,状态码:${response.status}"))
      }
    }
}

// 使用示例
val targetUrl = "https://lh3.googleusercontent.com/jUoaTIlBn5ibfQcND2n5OMD6Z7xoqNj-ShHlFR6QuLffLXD5pS8V2eNg1rGlrsRrnDkoQ28O8UHzqzBQKAGY4l1CS2NQSq2SkRScK6FOjl82jppyohK-"
getImageFromUrlInBytesAsync(targetUrl).onComplete {
  case scala.util.Success(bytes) => println(s"成功获取图片,字节数:${bytes.length}")
  case scala.util.Failure(e) => println(s"获取失败:${e.getMessage}")
}

注意事项

  • 同步方法会阻塞当前线程,适合简单低并发场景;异步方法适合高并发或非阻塞处理场景。
  • 所有实现都必须处理IO异常,比如网络中断、URL无效、目标资源不存在等情况。
  • 异步实现需注意ActorSystem的生命周期管理,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Shivam Sahil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:15:39