3

次のコードは、ファイルをサーバーにアップロードします。

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

public String uploadFileForStorage(String serverUrl, String filePath) {
StringBuilder responseMsg = new StringBuilder();
    try {
        final File file = new File(filePath);
        HttpParams httpParameters = new BasicHttpParams();
        // Set the timeout in milliseconds until a connection is
        // established.
        HttpConnectionParams.setConnectionTimeout(httpParameters, UPLOAD_CONNECTION_TIME_OUT);
        // Set the default socket timeout (SO_TIMEOUT)
        // in milliseconds which is the timeout for waiting for data.
        HttpConnectionParams.setSoTimeout(httpParameters, UPLOAD_SOCKET_TIME_OUT);

        HttpClient httpClient = new DefaultHttpClient(httpParameters);

        if (serverUrl.contains("?")) {
             serverUrl = Utils.getProperUrlWithOutEncode(serverUrl);
        }

        HttpPost postRequest = new HttpPost(serverUrl);
        FileBody bin = new FileBody(file);

        CustomMultiPartEntity multipartContent = new CustomMultiPartEntity(new ProgressListener() {
                        @Override
                        public void transferred(long num) {
                            total = total + num;
                        }
                    });
                    multipartContent.addPart(CUSTOM_FILE_TAG, bin);
                    postRequest.setEntity(multipartContent);
                    HttpResponse response = httpClient.execute(postRequest);
                    if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
                        String sResponse;
                        while ((sResponse = reader.readLine()) != null) {
                            responseMsg = responseMsg.append(sResponse);
                        }
                    } else {
                        responseMsg = responseMsg.append(String.valueOf(response.getStatusLine().getStatusCode()));
                    }
                } catch (Exception e) {
                    isError = true;
                }
                return responseMsg.toString();
            }

        }

タブレット SD カードからファイルをアップロードしています。上記のコードは、Samsung Galaxy Note 10.1 や Micromax Funbook 10 インチなどの複数の Android タブレットで正常に動作しますが、Samsung P6200 でファイルをアップロード中にクラッシュします。クラッシュはすぐには発生しませんが、アップロードの 5 ~ 10% 後に発生します。

以前は、アップロードは Samsung P6200 でも正常に機能していました。タブレットを出荷時設定にリセットしましたが、アップロード時のクラッシュが続きます。また、OutOfMemoryException は logcat に表示されません。ログには、クラス ファイルに NullPointerException が表示されますが、表示されるべきではありません。問題が HeapSize の問題であると仮定すると、どうすれば問題を処理できますか。

上記のコードを使用すると、Samsung Galaxy Note 10.1 や Micromax Funbook 10 などの Android タブレットで SIM(3G / WiFi) を使用して SDCard から最大 400 MB のファイルをアップロードできます。

次のコード行を追加すると役立つでしょうか?

HttpConnectionParams.setSocketBufferSize(httpParameters, 8192); 
// or any value other than //8192
4

1 に答える 1

0
                postRequest.setEntity(multipartContent);
                HttpResponse response = httpClient.execute(postRequest);

ヒープの問題が疑われる場合は、httpclient の実装/ソースを確認する必要があります。Apacheクライアントを使用していると思いますので、そこで確認してください。

メモリの問題が 2 つあります。

ファイルタグが(ソケットを使用する前に)メモリにマップされると、どのくらいの大きさで、どのような種類のバッファが使用されますか? ファイルをメモリにマップするコードを掘り下げて、使用可能なメモリ/バッファ サイズを小さくする必要がある場合があります。

ソケットがアップロードのために動作を開始すると、client.execute は別のバッファ サイクルを使用して、ファイル メモリから読み取り、アップロードに使用されているソケットに書き込みます。ソケット バッファ サイズの構成で遊ぶことに加えて、アップロードで「チャンク エンコーディング」(ストリーミング) を試すこともできます。ヘッダーをダンプすると、使用する Mime Multipart フォームが「chunked-encoding」の http ヘッダーにつながるかどうかを確認できるはずです。

大きなアップロードで機能するhttpUrlConnectionを使用したチャンクの例。ソースで「ChunkedStreamingMode」を見つけます。

于 2013-07-23T16:19:42.057 に答える