【问题标题】:Send an image with MultipartEntityBuilder and HttpURLConnection使用 MultipartEntityBuilder 和 HttpURLConnection 发送图像
【发布时间】:2017-07-04 18:01:05
【问题描述】:

我正在尝试使用 MultipartEntityBuilder 和 HttpURLConnection 将图像发送到服务器,然后收到字符串答案(现在它使用 http 协议,但我将使用此代码或非常类似的东西使用 https 来执行此操作)。但是当我按下按钮发送它时,应用程序崩溃了,logcat 没有告诉我任何关于捕获的信息。下一个是我做的类的代码:

public class EnvioImagenes extends AsyncTask<String, Void, String>
{
    public String direccion="";
    public EnvioImagenes(String cuerpo){
        direccion=cuerpo;
    }


    protected String doInBackground(String... url){
        Bitmap bitmap = null;
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
        ContentBody contentPart = new ByteArrayBody(bos.toByteArray(), direccion);
        MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
        multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntity.addPart("Picture",contentPart);

        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url[0]).openConnection();
            connection.setReadTimeout(10000);
            connection.setConnectTimeout(15000);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            //Si quiero enviar/recibir una respuesta en el cuerpo del mensaje, tiene que estar lo siguiente:
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Connection", "Keep-Alive");
            String boundary= "--------------"+System.currentTimeMillis();
            multipartEntity.setBoundary(boundary);
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            DataOutputStream dos=new DataOutputStream(connection.getOutputStream());
            //connection.addRequestProperty(multipartEntity.getClass().getName(), multipartEntity.getClass().toString());
            //OutputStream output=new BufferedOutputStream(connection.getOutputStream());
            dos.writeBytes("\r\n");
            dos.flush();
            dos.close();
            //output.write(body.getBytes());
            //output.flush();

            int responseCode = connection.getResponseCode();
            InputStream inputStream = connection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            StringBuilder result = new StringBuilder();

            while ((line = bufferedReader.readLine()) != null) {
                result.append(line);
            }

            String responseString = result.toString();
            inputStream.close();
            connection.disconnect();
            return responseString;

        } catch(Exception exc) {
            String error = exc.toString();
            Log.e("This is the mistake.....", exc.getMessage());
            return error;
        }
    }
}

我下载了 MultipartEntityBuilder 库,如下链接所示:Android - MultipartEntity and dependencies。问题是,当 build.gradle 检查一切是否正常时,它会向我显示以下警告:

Warning:WARNING: Dependency org.apache.httpcomponents:httpclient:4.5.3 is ignored for release as it may be conflicting with the internal version provided by Android.
         In case of problem, please repackage it with jarjar to change the class packages.

我试图解决它从浏览器下载包,然后将其粘贴到库内的文件夹 /lib 中,然后更改 build.gradle 中的代码以使程序从那里检查库,但随后我的错误是未检测到我使用 MultipartEntityBuilder 的代码中的库;所以我认为问题出在代码本身上:特别是因为我不使用 httpClient。对于任何问题,来自 build.gradle 的代码实际上是这样的:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"

    defaultConfig {
        applicationId "com.example.franco.pruebalogin"
        minSdkVersion 10
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.android.support:design:24.0.0'
    compile 'org.apache.httpcomponents:httpmime:4.5.3'
}

【问题讨论】:

    标签: java android httpurlconnection apache-httpclient-4.x android-library


    【解决方案1】:

    我走上了这条路,但最终转而使用SyncHttpClient

    private static final String COMPRESSED_FILE_PREFIX = "yourapp_image_compressed_";
    private static final String JPEG_FILE_EXTENSION = ".jpeg";
    private static final int FIVE_MINUTE_INIT_TIMEOUT = 300000;
    
    public void uploadImage(Context applicationContext, ArrayList<String> filePathsToUpload) {
            RequestParams requestParams = new RequestParams();
    
            File imagesCacheDir;
    
            if (android.os.Environment.getExternalStorageState().equals(
                    android.os.Environment.MEDIA_MOUNTED)) {
                imagesCacheDir = new File(
                        android.os.Environment.getExternalStorageDirectory(),
                        "/Android/data/com.example.yourapp/UploadPics");
            } else {
                imagesCacheDir = applicationContext.getCacheDir();
            }
    
            if (!imagesCacheDir.exists()) {
                if (!imagesCacheDir.mkdirs()) {
                    throw new RuntimeException("Image directory could not be created.");
                }
            }
    
            for (String filePath : filePathsToUpload) {
                File file;
    
                try {
                    FileOutputStream out = new FileOutputStream(new File(imagesCacheDir,
                            COMPRESSED_FILE_PREFIX + filePathsToUpload.size() + 1 + JPEG_FILE_EXTENSION));
    
                    BitmapFactory.decodeFile(filePath).compress(Bitmap.CompressFormat.JPEG, compress ? 90 : 100, out);
    
                    file = new File(imagesCacheDir, COMPRESSED_FILE_PREFIX + filePathsToUpload.size() + 1 + JPEG_FILE_EXTENSION);
                    requestParams.put(file.getName(), file);
                    out.close();
                } catch (FileNotFoundException fnfe) {
                    throw new RuntimeException("Image file not found.");
                } catch (IOException ie) {
                    throw new RuntimeException("Error writing image to file.);
                }
            }
    
            SyncHttpClient client = new SyncHttpClient();
            client.setTimeout(FIVE_MINUTE_INIT_TIMEOUT);
    
            Map<String, String> headers = VolleyUtils.getBigOvenHeaders();
            headers.putAll(VolleyUtils.getAuthenticationHeader());
    
            for (String headerKey : headers.keySet()) {
                client.addHeader(headerKey, headers.get(headerKey));
            }
    
            MySSLSocketFactory socketFactory;
    
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);
                socketFactory = new MySSLSocketFactory(trustStore);
                socketFactory.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                client.setSSLSocketFactory(socketFactory);
            } catch (Exception e) {
                // Probably should die or something, unless http is okay (if you need https, this is no go)
            }
    
            client.setTimeout(FIVE_MINUTE_INIT_TIMEOUT);
    
            client.post(this, "https://www.myapp.com/imageUploader", requestParams, new RotatingBitmapTextHttpResponseHandler(filePathsToUpload, notificationBuilder, onCompletionText));
    }
    

    您可以将 HttpResponseHandler 更改为您想要的任何内容。在这种情况下,我创建了一个跟踪进度并将其显示在通知中的类。你可以在那里做任何你想做的事情。

    【讨论】:

    • 我想要收到的答案是一个字符串,它表示服务器正确接收了图像。但是有了这个,你不是对图书馆有问题,还是直接你不需要它?之后如何从服务器接收答案?我想使用一些东西,然后我可以写一个 https 答案(今天我没有证书,所以我使用的是使用两次的东西,然后我会改变它)。我会在帖子中写任何问题
    • 您使用 TextHttpResponseHandler 来获取服务器的响应。将其传递给上面的 client.post() 方法。 onSuccess(int statusCode, Header[] headers, String responseString) 将为您提供所需的内容。
    • SyncHttpClient 能否在没有像 HttpUrlConnection 这样大的变化的情况下与 http 和 https 一起工作?它是否需要像 MultipartEntityBuilder 这样的额外库?
    • 我读到有一个名为 AsyncHttpClient 的类。和你给我看的课有很大的不同吗?我读到那个类可以使用 http 和 https...你知道吗?
    • 是第一个问题还是第二个问题?哈哈哈。你告诉我它可以做我想做的事,并且使用 http 和 https ......这就是我所需要的。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    相关资源
    最近更新 更多