Hp

HttpUrlConnectionを使用して、ファイルをアップロードするリクエストを投稿します



Use Httpurlconnection Post Request Upload Files



HttpUrlConnectionを使用してファイルアップロードの投稿フォームをシミュレートすることはめったに使用されないため、面倒です。

原則は次のとおりです。ファイルアップロードのデータ形式を分析し、その形式に従ってサーバーに送信される対応する文字列を作成します。



形式は次のとおりです。httppost123は私自身の文字列であり、他の任意の文字列にすることができます。

---------- httppost123( r n)
Content-Disposition:form-data name = 'img' filename = 't.txt'( r n)
コンテンツタイプ:アプリケーション/オクテットストリーム( r n)



( r n)

sdfsdfsdfsdfsdf( r n)
---------- httppost123( r n)
Content-Disposition:form-data name = 'text'( r n)

( r n)



テキストtttt( r n)
---------- httppost123-( r n)
( r n)

上記( r n)は、各データが( r n)で終わる必要があることを意味します。

具体的なJavaコードは次のとおりです。

import java.io.ByteArrayOutputStream import java.io.DataOutputStream import java.io.File import java.io.FileInputStream import java.io.InputStream import java.net.HttpURLConnection import java.net.SocketTimeoutException import java.net.URL import java.net.URLEncoder import java.util.HashMap import java.util.Iterator import java.util.Map import java.util.Set import javax.imageio.ImageIO import javax.imageio.ImageReader import javax.imageio.stream.ImageInputStream public class HttpPostUtil { URL url HttpURLConnection conn String boundary = '--------httppost123' Map textParams = new HashMap() Map fileparams = new HashMap() DataOutputStream ds public HttpPostUtil(String url) throws Exception { this.url = new URL(url) } / / Reset the server address to be requested, that is, the address of the uploaded file. public void setUrl(String url) throws Exception { this.url = new URL(url) } / / Add a normal string data to the form form data public void addTextParameter(String name, String value) { textParams.put(name, value) } / / Add a file to the form form data public void addFileParameter(String name, File value) { fileparams.put(name, value) } / / Clear all added form form data public void clearAllParameters() { textParams.clear() fileparams.clear() } / / Send data to the server, return a byte containing an array of the server's return results public byte[] send() throws Exception { initConnection() try { conn.connect() } catch (SocketTimeoutException e) { // something throw new RuntimeException() } ds = new DataOutputStream(conn.getOutputStream()) writeFileParams() writeStringParams() paramsEnd() InputStream in = conn.getInputStream() ByteArrayOutputStream out = new ByteArrayOutputStream() int b while ((b = in.read()) != -1) { out.write(b) } conn.disconnect() return out.toByteArray() } / / File upload connection must be set private void initConnection() throws Exception { conn = (HttpURLConnection) this.url.openConnection() conn.setDoOutput(true) conn.setUseCaches(false) conn.setConnectTimeout(10000) //Connection timeout is 10 seconds conn.setRequestMethod('POST') conn.setRequestProperty('Content-Type', 'multipart/form-data boundary=' + boundary) } / / ordinary string data private void writeStringParams() throws Exception { Set keySet = textParams.keySet() for (Iterator it = keySet.iterator() it.hasNext()) { String name = it.next() String value = textParams.get(name) ds.writeBytes('--' + boundary + ' ') ds.writeBytes('Content-Disposition: form-data name='' + name + '' ') ds.writeBytes(' ') ds.writeBytes(encode(value) + ' ') } } / / File data private void writeFileParams() throws Exception { Set keySet = fileparams.keySet() for (Iterator it = keySet.iterator() it.hasNext()) { String name = it.next() File value = fileparams.get(name) ds.writeBytes('--' + boundary + ' ') ds.writeBytes('Content-Disposition: form-data name='' + name + '' filename='' + encode(value.getName()) + '' ') ds.writeBytes('Content-Type: ' + getContentType(value) + ' ') ds.writeBytes(' ') ds.write(getBytes(value)) ds.writeBytes(' ') } } / / Get the file upload type, the image format is image / png, image / jpg and so on. Non-image is application/octet-stream private String getContentType(File f) throws Exception { // return 'application/octet-stream' // This line is no longer subdivided into images, all as application/octet-stream types ImageInputStream imagein = ImageIO.createImageInputStream(f) if (imagein == null) { return 'application/octet-stream' } Iterator it = ImageIO.getImageReaders(imagein) if (!it.hasNext()) { imagein.close() return 'application/octet-stream' } imagein.close() Return 'image/' + it.next().getFormatName().toLowerCase()//Converts the value returned by FormatName to lowercase, defaults to uppercase } / / Convert the file into a byte array private byte[] getBytes(File f) throws Exception { FileInputStream in = new FileInputStream(f) ByteArrayOutputStream out = new ByteArrayOutputStream() byte[] b = new byte[1024] int n while ((n = in.read(b)) != -1) { out.write(b, 0, n) } in.close() return out.toByteArray() } / / Add end data private void paramsEnd() throws Exception { ds.writeBytes('--' + boundary + '--' + ' ') ds.writeBytes(' ') } // Transcode a string containing Chinese, which is UTF-8. The server has to decode once private String encode(String value) throws Exception{ return URLEncoder.encode(value, 'UTF-8') } public static void main(String[] args) throws Exception { HttpPostUtil u = new HttpPostUtil('http://localhost:3000/up_load') u.addFileParameter('img', new File( 'D:\materials ound.jpg')) u.addTextParameter('text', 'Chinese') byte[] b = u.send() String result = new String(b) System.out.println(result) } }

受け取るためにルビーを使用して舞台裏

ルビーコードは次のとおりです:

require 'cgi' class UpLoadController :index def index img = params[:img] if img.kind_of? String logger.debug 'img string : #{img}' else logger.debug 'Content-Type:#{img.content_type}' logger.debug 'or:#{CGI.unescape(img.original_filename)}' end text = params[:text] logger.debug 'text:#{CGI.unescape(text)}' render :text=>'OK' end end

ログ入力は次のとおりです。

コンテンツタイプ:image / jpeg
または:round moon.jpg
テキスト:中国語

中国語が送信用にUTF-8形式に変換されていない場合、中国語の文字化けが背景に表示されます。

同様に、他のパラメータに中国語が含まれている場合は、最初にトランスコードする必要があります。

もちろん、どの特定のエンコーディングがバックグラウンドで受信されたエンコーディングと一致している必要があります。

また、c#に慣れていないため、c#コードを添付しましたが、コードテストは基本的に実行できます。

|_+_|

私のネイティブテストでは、文字化けした中国語はありません。

c#呼び出しメソッド:

|_+_|

エラーがある場合は追加してください。