当前位置: 首页 > 知识库问答 >
问题:

如何通过HTTP POST方法使用Retrofit或Picasso下载图像

姚俊材
2023-03-14

我有一个HTTP post请求,它以一个JSON作为请求体,其中包含以下内容:

{
  "UserName":"ApiService", 
  "Password":"BandarAndroid",
  "AndroidId":"15df3b3a90XXXXX",
  "ContentId":"704",
  "frame":"1"
}

向服务器请求后,我只得到一个图像作为响应(而不是任何东西(如JSON))。适当的图像是根据请求创建的,没有网址。我的服务地址是:

http://xyz.website.com/api/DownloadFileForAndroid

我的回复标题是:

cache-control →no-cache
content-length →29837
content-type →image/png
date →Mon, 09 Sep 2019 08:42:23 GMT
expires →-1
pragma →no-cache
server →Microsoft-IIS/8.5
x-aspnet-version →4.0.30319
x-powered-by →ASP.NET

我不知道是用改造还是毕加索来得到这张照片,

在Picasso中:我无法发送请求正文中的JSON数量。

在改造:我不能没有url的照片(地址指向照片像www.site.com/a.jpg)

共有2个答案

严烨
2023-03-14

我不知道是用翻新还是毕加索来得到这张照片

最好使用Picasso,否则如果您使用Retrofit下载图像,您必须编写大量代码才能有效地加载图像。

您很高兴知道,根据您从该API加载图像的选择,您可以同时使用改装和毕加索。

在继续进行示例之前,我想澄清一点,您有一个误解,即需要将上述JSON数据作为头发送,但在使用API之后,我发现它将JSON作为请求体。

远程pi.kt

interface RemoteApi {
    // Retrofit
    @Streaming  // Important
    @POST("/api/DownloadFileForAndroid")
    @Throws(Exception::class)
    suspend fun getImage(@Body body: ImageRequest): ResponseBody?

    companion object {
        // Retrofit
        fun create(): RemoteApi {
            val retrofit = Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("http://shop.atiafkar.ir")
                    .build()
            return retrofit.create(RemoteApi::class.java)
        }
        // Picasso
        fun getPicassoImageRequest(
                builder : Picasso.Builder,
                body: String,
                url: String = "http://shop.atiafkar.ir/api/DownloadFileForAndroid"
        ) = builder.downloader(OkHttp3Downloader(getPicassoCallFactory(body)))
                        .build()
                        .load(url)
        // Picasso
        private fun getPicassoCallFactory(jsonBody : String): Call.Factory {
            return Call.Factory { request ->
                OkHttpClient().run {
                    RequestBody.create(MediaType.parse("application/json"), jsonBody).let {
                        newCall(request.newBuilder()
                                .post(it)
                                .addHeader("Content-Type", "application/json")
                                .build()
                        )
                    }
                }
            }
        }
    }
}

ImageRepository。千吨级

class ImageRepository(private val api: RemoteApi = RemoteApi.create()) {
    companion object {
        fun get() = ImageRepository()
    }
    // Retrofit
    suspend fun downloadImage(body : ImageRequest = ImageRequest.default): Bitmap? {
        return api.getImage(body)?.run {
            withContext(Dispatchers.IO) {
                bytes().let {
                    // to load bitmap efficiently follow the guideline provided by -
                    //  https://developer.android.com/topic/performance/graphics/load-bitmap
                    // otherwise you may experience OutOfMemoryException
                    BitmapFactory.decodeByteArray(it, 0, it.size)
                }
            }
        }
    }
    // Picasso
    fun getPicassoImageLoader(
            builder : Picasso.Builder,
            body: ImageRequest = ImageRequest.default
    ) = RemoteApi.getPicassoImageRequest(builder, body.toJson())
}

ImageViewModel。千吨级

class ImageViewModel(private val repository: ImageRepository) : ViewModel() {
    private val _progress = MutableLiveData<Boolean>()
    val progress = _progress
    // Retrofit
    val liveImage = liveData {
        _progress.value = true
        emit(repository.downloadImage())
        _progress.value = false
    }
    // Picasso
    fun getPicassoImageLoader(builder: Picasso.Builder) = repository.getPicassoImageLoader(builder)
}

最后

图片ctivity.kt

class ImageActivity : AppCompatActivity() {
    private lateinit var dataBinding : ActivityImageBinding
    private val imageViewModel by lazy { ViewModelProviders.of(this, ImageViewModelFactory()).get(ImageViewModel::class.java) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_image)
        dataBinding.lifecycleOwner = this
        dataBinding.viewModel = imageViewModel
        // Retrofit
        imageViewModel.liveImage.observe(this, Observer {
            dataBinding.imageView.setImageBitmap(it)
        })
        // Picasso
        imageViewModel.getPicassoImageLoader(Picasso.Builder(this)).into(dataBinding.imageView2)
    }
}

ImageRequest。千吨级

data class ImageRequest(
        @field:SerializedName("UserName")
        val userName: String? = null,
        @field:SerializedName("ContentId")
        val contentId: String? = null,
        @field:SerializedName("AndroidId")
        val androidId: String? = null,
        @field:SerializedName("Password")
        val password: String? = null,
        @field:SerializedName("frame")
        val frame: String? = null
) {
    companion object {
        val default = ImageRequest(
                "ApiService",
                "704",
                "15df3b3a90dc5688",
                "BandarAndroid",
                "1"
        )
    }
}

fun ImageRequest.toJson() : String {
    return Gson().toJson(this, ImageRequest::class.java)
}
龚联
2023-03-14

根据您的要求,我正在将以前的解决方案(Kotlin)转换为Java

public void loadImageWithPicasso(ImageView imageView) {
    Picasso.Builder builder = new Picasso.Builder(imageView.getContext());
    RequestCreator picassoImageLoader = createPicassoLoader(
            builder,
            ImageRequest.DEFAULT_JSON_BODY,
            "http://shop.atiafkar.ir/api/DownloadFileForAndroid"
    );
    picassoImageLoader.into(imageView);
}

public RequestCreator createPicassoLoader(Picasso.Builder builder, String body, String url) {
    return builder.downloader(new OkHttp3Downloader(createPicassoCallFactory(body)))
            .build()
            .load(url);
}

private okhttp3.Call.Factory createPicassoCallFactory(String jsonBody) {
    final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .build();
    final RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), jsonBody);
    return new okhttp3.Call.Factory() {
        @Override
        public okhttp3.Call newCall(Request request) {
            Request.Builder builder = request.newBuilder();
            builder.post(requestBody);
            builder.addHeader("Content-Type", "application/json");
            return okHttpClient.newCall(builder.build());
        }
    };
}
public void loadImageWithRetrofit(ImageView imageView) {
        final RetrofitImageLoader imageLoader = new RetrofitImageLoader(imageView);
        RemoteApi api = RemoteApi.Factory.create();

        api.getImage(ImageRequest.DEFAULT_BODY).enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                ResponseBody body = response.body();
                if (response.isSuccessful() && body != null) {
                    imageLoader.execute(body.byteStream());
                } else {
                    Log.d(TAG, "Retrofit onResponse(): CODE = [" + response.code() + "], MESSAGE = [" + response.message() + "]");
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.d(TAG, "Retrofit onFailure(): t = [" + t + "]");
            }
        });
}

RetrofitImageLoader

public class RetrofitImageLoader extends AsyncTask<InputStream, Integer, Bitmap> {
        private ImageView imageView;

        private RetrofitImageLoader(ImageView imageView) {
            this.imageView = imageView;
        }

        @Override
        protected Bitmap doInBackground(InputStream... inputStreams) {
            return BitmapFactory.decodeStream(inputStreams[0]);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            imageView.setImageBitmap(bitmap);
        }
}

远程API接口

public interface RemoteApi {
    @Streaming  // Important
    @POST("/api/DownloadFileForAndroid")
    Call<ResponseBody> getImage(@Body ImageRequest body);

    class Factory {
        private static RemoteApi mInstance;

        public static RemoteApi create() {
            if (mInstance == null) {
                mInstance = new Retrofit.Builder()
                        .addConverterFactory(GsonConverterFactory.create())
                        .baseUrl("http://shop.atiafkar.ir")
                        .build()
                        .create(RemoteApi.class);
            }
            return mInstance;
        }
    }
}

ImageRequest模型

public class ImageRequest{
    public static final ImageRequest DEFAULT_BODY;
    public static final String DEFAULT_JSON_BODY;

    static {
        DEFAULT_BODY = new ImageRequest();
        DEFAULT_BODY.setAndroidId("15df3b3a90dc5688");
        DEFAULT_BODY.setContentId("704");
        DEFAULT_BODY.setFrame("1");
        DEFAULT_BODY.setPassword("BandarAndroid");
        DEFAULT_BODY.setUserName("ApiService");

        DEFAULT_JSON_BODY = new Gson().toJson(DEFAULT_BODY, ImageRequest.class);
    }

    @SerializedName("UserName")
    private String userName;
    @SerializedName("ContentId")
    private String contentId;
    @SerializedName("AndroidId")
    private String androidId;
    @SerializedName("Password")
    private String password;
    @SerializedName("frame")
    private String frame;

    public void setUserName(String userName){
        this.userName = userName;
    }
    public void setContentId(String contentId){
        this.contentId = contentId;
    }
    public void setAndroidId(String androidId){
        this.androidId = androidId;
    }
    public void setPassword(String password){
        this.password = password;
    }
    public void setFrame(String frame){
        this.frame = frame;
    }
}
 类似资料:
  • 我希望方法使用picasso从服务器加载图像,并且我希望显示一个进度条,直到照片完全下载完毕。下面是我的代码:

  • 问题内容: 我们有一个Web应用程序,需要通过http从合作伙伴站点导入10-20张图像。如果我有一个代表要下载的URL的字符串列表,是否有人建议如何尽快下载它们? 我可以将它们放在for循环中,但是如果有一种简单的方法可以并行化它,那么这对最终用户可能会有所帮助。尽管执行程序框架可能是个好主意,但我还是想避免使用直接的Java线程。 有任何想法吗? 问题答案: Executor框架正是您想要的。

  • 有没有一种方法可以通过curl或wget下载一个可公开查看的Google Drive url?例如,能够做类似的事情: 注意,我希望在一个可公开查看的文件上这样做,而不需要登录到我的Google帐户(或者让其他人登录到他们的帐户,等等)。 如果有帮助,我有的cors头是:

  • 本文向大家介绍Python3下载文件或图片方法,包括了Python3下载文件或图片方法的使用技巧和注意事项,需要的朋友参考一下 1、使用requests 2、使用urllib.request.urlretrieve

  • 问题内容: 我有以下代码,可以轻松连接到FTP服务器并打开一个zip文件。我想将该文件下载到本地系统。怎么做? 问题答案:

  • 我正在编写一个python脚本,它将根据URL中给定的格式在本地保存pdf文件。例如。 我正在通过python脚本打开此URL: url包含大量图像和文本。一旦这个URL被打开,我想用python脚本以pdf格式保存一个文件。 这是我到目前为止所做的。 代码1: 代码2: 在上面的代码我得到: urllib2.HTTP错误401:未授权 如果使用代码2,如何传递授权详细信息?