Htmlがどのように機能するかはほとんどわかりません。私がやりたいことは、次の例とまったく同じですAndroidの場合
<body>
<form action="<%= some_url %>" method="post" enctype="multipart/form-data">
<input type="file" name="myFile">
<input type="submit" value="Submit">
</form>
</body>
私は次のコードを試しました-
private static void postToUrl(String url_to_upload_on,
String file_name_with_ext, byte[] byteArray) {
String attachmentName = "file";
String attachmentFileName = file_name_with_ext;
String crlf = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try{
URL url = new URL(url_to_upload_on);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(
connection.getOutputStream());
request.writeBytes(twoHyphens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data; name=\"" +
attachmentName + "\";filename=\"" +
attachmentFileName + "\"" + crlf);
request.writeBytes(crlf);
request.write(byteArray);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary +
twoHyphens + crlf);
request.flush();
request.close();
}catch(Exception e){
e.printStackTrace();
}
}
これは私に直接的なエラーを与えませんが、エラーストリームを使用して
Log.w(TAG, "connection.getErrorStream() = " + connection.getErrorStream());
私はこれを得る-
12-14 18:25:54.911: W/uploadToBlobStore(30558): httpUrlConnection.getErrorStream() = com.Android.okhttp.internal.http.HttpTransport$FixedLengthInputStream@426dd5a8
成功なし。
PS-ファイルをGoogle Blobstoreにアップロードしています
PS- Androidが減価償却されていると言うので、Apache HTTPライブラリまたはそのマルチパートクラスを使用できません
編集1
今、私は次のコードを使用していますが、2.3Mb未満のファイルでのみ動作しています-
private static void postToUrl3(String url_to_upload_on,
String file_name_with_ext, byte[] byteArray, String mimeType) {
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClientBuilder.create().build();
HttpPost postRequest = new HttpPost(url_to_upload_on);
MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
reqEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ByteArrayBody bab = new ByteArrayBody(byteArray, file_name_with_ext);
reqEntity.addPart("file", bab);
postRequest.setEntity(reqEntity.build());
httpClient.execute(postRequest);// takes time
} catch (Exception e) {
Log.w("uploadToBlobStore", "postToUrl Exception e = " + e);
e.printStackTrace();
} finally {
if (httpClient != null) {
Log.w("uploadToBlobStore", "connection.closing ");
try {
httpClient.close();
} catch (IOException e) {
Log.w("uploadToBlobStore", "connection.closing errot e = "
+ e);
e.printStackTrace();
}
}
}
}
大きなファイルでそれを動作させる方法は?
PS-私はそれをブロブストアに送信しており、maxUploadSizeBytes
およびMaxUploadSizeBytesPerBlob
を30MBに設定しました。Googleブロブストアのドキュメントには、
Google App EngineにはBlobstoreサービスが含まれています。これにより、アプリケーションは、単一のHTTP接続でアップロードまたはダウンロードできるデータの量によってのみ制限されるデータオブジェクトを提供できます。
では、HTTP接続に問題があるのでしょうか?もしそうなら、どのように設定できますか?.
これを達成するためにHttpURLConnection
を使用しています。
マルチパートカスタムクラスを1つ作成::
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
*
* @param requestURL
* @param charset
* @throws IOException
*/
public MultipartUtility(String requestURL, String charset)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
/**
* Adds a form field to the request
*
* @param name field name
* @param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
*
* @param fieldName name attribute in <input type="file" name="..." />
* @param uploadFile a File to be uploaded
* @throws IOException
*/
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
/**
* Adds a header field to the request.
*
* @param name - name of the header field
* @param value - value of the header field
*/
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
*
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
public List<String> finish() throws IOException {
List<String> response = new ArrayList<String>();
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
// checks server's status code first
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
return response;
}
}
それを使用する(非同期の方法)::
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
// In your case you are not adding form data so ignore this
/*This is to add parameter values */
for (int i = 0; i < myFormDataArray.size(); i++) {
multipart.addFormField(myFormDataArray.get(i).getParamName(),
myFormDataArray.get(i).getParamValue());
}
//add your file here.
/*This is to add file content*/
for (int i = 0; i < myFileArray.size(); i++) {
multipart.addFilePart(myFileArray.getParamName(),
new File(myFileArray.getFileName()));
}
List<String> response = multipart.finish();
Debug.e(TAG, "SERVER REPLIED:");
for (String line : response) {
Debug.e(TAG, "Upload Files Response:::" + line);
// get your server response here.
responseString = line;
}
okhttp を使用し、次のスニペットを使用します( recipes から取得)
サーバーの期待に応じてヘッダー値を調整します。
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
代わりにRetrofitを使用できます。
次のような呼び出しを指定できます。
@Multipart
@POST("/user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
次のように作成します:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.build();
GitHubService service = retrofit.create(GitHubService.class);
最後に次のように実行します:
service.updateUser(Photo, description).enqueue()
->asynchronous
service.updateUser(Photo, description).execute()
->synchronous
ドキュメントを参照してください here