【问题标题】:gradle - download and unzip file from urlgradle - 从 url 下载和解压缩文件
【发布时间】:2014-05-26 05:27:40
【问题描述】:

从 url (http) 下载和解压缩文件的正确 gradle 方式是什么?

如果可能,我想防止每次运行任务时都重新下载(在ant.get 可以通过skipexisting: 'true' 实现)。

我目前的解决方案是:

task foo {
  ant.get(src: 'http://.../file.zip', dest: 'somedir', skipexisting: 'true')
  ant.unzip(src: 'somedir' + '/file.zip', dest: 'unpackdir')
}

不过,我希望没有蚂蚁的解决方案。有机会实现吗?

【问题讨论】:

  • 不要忘记用doLast { ... } 包装任务的执行部分(与上一个问题中的错误相同)。
  • ~~BOUNTY~~ 谁能为下面的答案提供一个示例:“如果您确实想从 Gradle 的依赖解析/缓存功能中受益,请假装它是具有自定义工件 URL 的 Ivy 存储库” ?
  • netflix 发布了一些插件:github.com/nebula-plugins/nebula-core - 不确定,为什么不再维护。

标签: http download gradle unzip


【解决方案1】:

假设您要下载此 zip 文件作为依赖项:

https://github.com/jmeter-gradle-plugin/jmeter-gradle-plugin/archive/1.0.3.zip

你将你的 ivy repo 定义为:

repositories {
    ivy {
        url 'https://github.com/'

        patternLayout {
            artifact '/[organisation]/[module]/archive/[revision].[ext]'
        }

        // This is required in Gradle 6.0+ as metadata file (ivy.xml) 
        // is mandatory. Docs linked below this code section
        metadataSources { artifact() } 
    }
}

所需元数据的参考here

然后可以将依赖项用作:

dependencies {
    compile 'jmeter-gradle-plugin:jmeter-gradle-plugin:1.0.3@zip'
    //This maps to the pattern: [organisation]:[module]:[revision]:[classifier]@[ext]         
}

解压:

task unzip(type: Copy) {

  def zipPath = project.configurations.compile.find {it.name.startsWith("jmeter") }
  println zipPath
  def zipFile = file(zipPath)
  def outputDir = file("${buildDir}/unpacked/dist")

  from zipTree(zipFile)
  into outputDir

}

可选:

如果您的项目中有多个存储库,它也可能有助于(为了构建时间和一定程度的安全性)限制相关存储库的依赖项搜索。

Gradle 6.2+:

repositories {
    mavenCentral()
    def github = ivy {
        url 'https://github.com/'
        patternLayout {
            artifact '/[organisation]/[module]/archive/[revision].[ext]'
        }
        metadataSources { artifact() }
    }
    exclusiveContent {
        forRepositories(github)
        filter { includeGroup("jmeter-gradle-plugin") }
    }
}

早期的 gradle 版本:

repositories {
    mavenCentral {
        content { excludeGroup("jmeter-gradle-plugin") }
    }
    ivy {
        url 'https://github.com/'
        patternLayout {
            artifact '/[organisation]/[module]/archive/[revision].[ext]'
        }
        metadataSources { artifact() }
        content { includeGroup("jmeter-gradle-plugin") }
    }
}

【讨论】:

  • 不幸的是,不能以这种方式访问​​带有查询字符串的 URL,'?'由github.com/gradle/gradle/blob/master/subprojects/resources/src/… 编码
  • 当我尝试这个而不是寻找 .zip 文件时,它正在寻找一个 .xml 文件。有什么办法吗?我遵循了完全相同的说明。
  • 对我不起作用。除了工件之外,Gradle 还在寻找 ivy.xml 文件。
  • 这是一个很好的答案。我只想补充一点,依赖项可能应该是 compileOnly 以防止原始 zip 最终出现在运行时工件中。
  • 我可以确认这适用于 7.2,@rios0rios0 你解决了吗?
【解决方案2】:
    plugins {
        id 'de.undercouch.download' version '4.0.0'
    }

    /**
     * The following two tasks download a ZIP file and extract its
     * contents to the build directory
     */
    task downloadZipFile(type: Download) {
        src 'https://github.com/gradle-download-task/archive/1.0.zip'
        dest new File(buildDir, '1.0.zip')
    }

    task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) {
        from zipTree(downloadZipFile.dest)
        into buildDir
    }

https://github.com/michel-kraemer/gradle-download-task

【讨论】:

  • 与 Ant 相比,这并不是一个很好的解决方案,因为它真的很慢。下载 26 分钟,而不是使用 Chrome 的 2 分钟。
【解决方案3】:

“native gradle”,只有下载部分(解压见其他答案)

task foo {
  def src = 'http://example.com/file.zip'
  def destdir = 'somedir'
  def destfile = "$destdir/file.zip"
  doLast {
    def url = new URL(src)
    def f = new File(destfile)
    if (f.exists()) {
      println "file $destfile already exists, skipping download"
    } else {
      mkdir "$destdir"
      println "Downloading $destfile from $url..."
      url.withInputStream { i -> f.withOutputStream { it << i } }
    }
  }
}

【讨论】:

    【解决方案4】:

    这适用于 Gradle 5(使用 5.5.1 测试):

    task download {
        doLast {
            def f = new File('file_path')
            new URL('url').withInputStream{ i -> f.withOutputStream{ it << i }}
        }
    }
    

    调用gradle download 将文件从url 下载到file_path

    如有必要,您可以使用其他答案中的其他方法解压缩文件。

    【讨论】:

    • 也适用于 gradle 4.7。以防有人需要。
    【解决方案5】:

    我得到了@RaGe 的答案,但我不得不调整它,因为 ivy 布局方法已被贬值,请参阅 https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html#org.gradle.api.artifacts.repositories.IvyArtifactRepository:layout(java.lang.String,%20groovy.lang.Closure)

    所以为了让它工作,我必须为 tomcat keycloak 适配器调整它:

    ivy {
        url 'https://downloads.jboss.org/'
        patternLayout {
            artifact '/[organization]/[revision]/adapters/keycloak-oidc/[module]-[revision].[ext]'
        }
    }
    
    dependencies {
        // https://downloads.jboss.org/keycloak/4.8.3.Final/adapters/keycloak-oidc/keycloak-tomcat8-adapter-dist-4.8.3.Final.zip
        compile "keycloak:keycloak-tomcat8-adapter-dist:$project.ext.keycloakAdapterVersion@zip"
    }
    
    task unzipKeycloak(type: Copy) {
    
        def zipPath = project.configurations.compile.find {it.name.startsWith("keycloak") }
        println zipPath
        def zipFile = file(zipPath)
        def outputDir = file("${buildDir}/tomcat/lib")
    
        from zipTree(zipFile)
        into outputDir
    }
    

    【讨论】:

    • 不幸的是,这个解决方案还让 Gradle 寻找 Ivy XML 文件。
    • 不起作用。 Gradle 7.2 正在寻找一个正常的 maven 依赖项。
    【解决方案6】:

    使用复制任务解压的过程如下:

    task unzip(type: Copy) {
      def zipFile = file('src/dists/dist.zip')
      def outputDir = file("${buildDir}/unpacked/dist")
    
      from zipTree(zipFile)
      into outputDir
    }
    

    http://mrhaki.blogspot.de/2012/06/gradle-goodness-unpacking-archive.html

    【讨论】:

    • 我尝试将from zipTree() &amp; into outputDir 移至执行阶段,方法是将它们移至doLast { }。我不明白的是它从来没有奏效。即使doLast 中的println 代码也不起作用。但是,此代码在 gradle 配置阶段有效。为什么?
    • 因为它配置了任务。执行仍然在执行阶段完成。实际上不应该在执行阶段更改配置,在您的情况下,执行阶段根本不会执行,因为任务认为没有什么可复制的,因此跳过任务执行。但实际上这个答案与问题无关,因为这不适用于 HTTP URL。
    【解决方案7】:

    目前没有用于从 URL 下载的 Gradle API。您可以使用 Ant、Groovy 来实现这一点,或者,如果您确实想从 Gradle 的依赖解析/缓存功能中受益,可以假装它是一个具有自定义工件 URL 的 Ivy 存储库。可以通过通常的 Gradle 方式(copy 方法或Copy 任务)完成解压缩。

    【讨论】:

    • 我会很感激一个例子...我是一个完全的 gradle 新手!
    • ~~BOUNTY~~ 谁能为这个答案提供一个例子“如果你确实想从 Gradle 的依赖解析/缓存功能中受益,假装它是一个具有自定义工件 URL 的 Ivy 存储库”?
    • @CMPS 为什么你没有 groovy?
    • @CMPS 啊,缓存!在下面发布了答案。
    猜你喜欢
    • 1970-01-01
    • 2021-09-27
    • 2016-09-06
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多