问题
After much googling and searching, I managed to send an image using multiparsers from android to my WCF service, but ideally, I'd like to send several images at once, instead of calling the method over and over again, since it'd take a lot longer, and add a bunch more overhead.
This is my current code
Android (Taken from code found on here somewhere):
public static String postFile(Bitmap bitmap, String urlString) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlString);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 30, bao);
byte[] data = bao.toByteArray();
//filename
String fileName = String.format("File_%d.png",new Date().getTime());
ByteArrayBody bab = new ByteArrayBody(data, fileName);
builder.addPart("image", bab);
final HttpEntity yourEntity = builder.build();
class ProgressiveEntity implements HttpEntity {
@Override
public void consumeContent() throws IOException {
yourEntity.consumeContent();
}
@Override
public InputStream getContent() throws IOException,
IllegalStateException {
return yourEntity.getContent();
}
@Override
public Header getContentEncoding() {
return yourEntity.getContentEncoding();
}
@Override
public long getContentLength() {
return yourEntity.getContentLength();
}
@Override
public Header getContentType() {
return yourEntity.getContentType();
}
@Override
public boolean isChunked() {
return yourEntity.isChunked();
}
@Override
public boolean isRepeatable() {
return yourEntity.isRepeatable();
}
@Override
public boolean isStreaming() {
return yourEntity.isStreaming();
} // CONSIDER put a _real_ delegator into here!
@Override
public void writeTo(OutputStream outstream) throws IOException {
class ProxyOutputStream extends FilterOutputStream {
/**
* @author Stephen Colebourne
*/
public ProxyOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(int idx) throws IOException {
out.write(idx);
}
public void write(byte[] bts) throws IOException {
out.write(bts);
}
public void write(byte[] bts, int st, int end) throws IOException {
out.write(bts, st, end);
}
public void flush() throws IOException {
out.flush();
}
public void close() throws IOException {
out.close();
}
} // CONSIDER import this class (and risk more Jar File Hell)
class ProgressiveOutputStream extends ProxyOutputStream {
public ProgressiveOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(byte[] bts, int st, int end) throws IOException {
// FIXME Put your progress bar stuff here!
out.write(bts, st, end);
}
}
yourEntity.writeTo(new ProgressiveOutputStream(outstream));
}
};
ProgressiveEntity myEntity = new ProgressiveEntity();
post.setEntity(myEntity);
HttpResponse response = client.execute(post);
return getContent(response);
}
public static String getContent(HttpResponse response) throws IOException {
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String body = "";
String content = "";
while ((body = rd.readLine()) != null)
{
content += body + "\n";
}
return content.trim();
}
C# WCF Service method to take it
[WebInvoke(UriTemplate = "UploadPicture/{filename}", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public String UploadPicture(string filename, Stream fileStream)
{
WriteLog("Uploading picture...");
try
{
MultipartParser parser = new MultipartParser(fileStream);
if (parser.Success)
{
string fileName = parser.Filename;
string contentType = parser.ContentType;
byte[] fileContent = parser.FileContents;
FileStream fileToupload = new FileStream("\\\\OHS-SUN\\Tracker\\robbie\\" + filename, FileMode.Create);
fileToupload.Write(fileContent, 0, fileContent.Length);
fileToupload.Close();
fileToupload.Dispose();
fileStream.Close();
return "Success !!!";
}
else
{
return "Exception!!!";
}
}
catch (Exception ex)
{
WriteLog("Uploading picture exception: " + ex.Message);
}
return "Picture uploaded!";
}
I'd like to go from sending one image, to sending several, each with 2 text attributes; the filename, and the project number they're associated with. Essentially, both is what I need it for. At the moment, I'm just trying to do put another addPart on to the android bit, but then I don't know how to add metadata to that and I wouldn't know how to parse it based on the name. I'm fine with using any third party libraries, the one I'm using on C# at the moment is already one.
Thanks a lot!
回答1:
Instead of sending multiple images in one thing, I just stuck it in an asynchronous class and sent them concurrently with a max of 10 at a time until all the images are sent in that particular session. Seems to work fine, the implementation's the same, so I've not had to change any of that, which is good. If anyone would like me to post the code I did to do that, I'd be happy to. It's just small snippets here and there added to the above code, though.
Well, the main bit I added was:
public static class FileUploader extends AsyncTask<UploadFile , Void , String> implements Future<String>
{
@Override
protected void onPreExecute() {
filesUploading ++;
}
@Override
protected String doInBackground(UploadFile... uploadFile)
{
try
{
return postFile(uploadFile[0].file, uploadFile[0].projectNo, uploadFile[0].filename);
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
filesUploading --;
}
@Override
public boolean isDone() {
return AsyncTask.Status.FINISHED == getStatus();
}
}
This allows me to send each image separately, and handle them separately.
来源:https://stackoverflow.com/questions/22101515/how-to-send-multiple-images-from-android-to-a-wcf-rest-service-as-a-stream-to-wr