2016-03-23 11 views
1

Ich versuche, eine Datei von Android auf einen WCF-Dienst hochzuladen. Ich bin an den Punkt gekommen, wo die Methode auf der WCF ausgelöst wird und die Datei speichert. Beim Versuch, die Datei zu öffnen, erhalte ich eine Fehlermeldung, die besagt, dass sie beschädigt ist.C# & Java - Hochladen einer Datei von Android auf WCF

Ich denke, der Fehler könnte in der HttpFileUpload-Klasse sein, dass eine der statischen Variablen falsch ist oder dass was ich sende ist kein Stream, sondern etwas anderes, dass der Dienst in einen Stream irgendwie die Korruption umgewandelt .

Der verwendete Code kann unten gefunden werden.

Android Code:

HttpFileUpload Klasse:

Der HttpFileUpload Code gefunden here:

private static final String LINE_FEED = "\r\n"; 
private String charset = "UTF-8"; 

public HttpFileUpload(String requestURL) throws IOException { 

    // 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); 
    httpConn.setRequestProperty("Host", "x.x.x.x:x"); 
    outputStream = httpConn.getOutputStream(); 
    writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true); 
} 

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); // form-data 
    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(); 
} 

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(); 

    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 status: " + status); 
    } 

    return response; 
} 

Service Connector Klasse

String urlTo = LOCATION + "/UploadUserProfilePicture"; 
    File file = new File(imagePath); 

    try { 
     HttpFileUpload httpFileUpload = new HttpFileUpload(urlTo); 

     httpFileUpload.addFilePart("image", file); 

     List<String> responses = httpFileUpload.finish(); 

     for (String line : responses) { 
      System.out.println(line); 
     } 

     return responses.get(0); 

    } catch (Exception ex) { 
     return ex.toString(); 
    } 

WCF-Servicecode

IMobileService:

[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
    [OperationContract] 
    Result UploadUserProfilePicture(Stream image); 

MobileService:

Die FileType fileType = bytes.GetFileType() ist ein Plugin, das die Erweiterung zurückgibt. Derzeit funktioniert das Plugin nicht, da der Dateityp immer null ist. Die Bildvariable ist jedoch möglicherweise bereits beschädigt.

Antwort

0

Danke Thorsten, dass er mich in die richtige Richtung geführt hat. Hier ist ein codiertes Beispiel:

Android Code:
ImageUploading Aktivität:

File initialFile = new File(imagePath); 

byte[] bytes = FileUtils.readFileToByteArray(initialFile); 
final String base64 = android.util.Base64.encodeToString(bytes, android.util.Base64.DEFAULT); 

Thread uploadFileThread = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     FileToUpload fileToUpload = new FileToUpload(); 
     fileToUpload.setFile(base64); 
     String[] result = ServiceConnector.UploadUserProfilePicture(fileToUpload); 
    } 
}); 

ServiceConnector Klasse:

public static String[] UploadUserProfilePicture(FileToUpload fileToUpload) { 

StringBuilder sb = new StringBuilder(); 
String result[] = {"false", "Something went wrong"}; 

HttpURLConnection urlConnection = null; 
try { 
    URL url; 
    DataOutputStream printout; 
    DataInputStream input; 
    url = new URL(LOCATION + "/UploadUserProfilePicture"); 
    urlConnection = (HttpURLConnection) url.openConnection(); 
    urlConnection.setDoInput(true); 
    urlConnection.setDoOutput(true); 
    urlConnection.setUseCaches(false); 
    urlConnection.setRequestProperty("Content-Type", "application/json"); 
    urlConnection.setRequestProperty("Host", "x.x.x.x:xxxx"); 
    urlConnection.setConnectTimeout(1*1000*3600); 
    urlConnection.setReadTimeout(1*1000*3600); 
    urlConnection.connect(); 

    GsonBuilder builder = new GsonBuilder(); 
    Gson gson = builder.create(); 

    // Send POST output. 
    printout = new DataOutputStream(urlConnection.getOutputStream()); 
    byte[] extraInfo = gson.toJson(fileToUpload).getBytes("UTF-8"); 
    printout.write(extraInfo); 
    printout.flush(); 
    printout.close(); 

    int HttpResult = urlConnection.getResponseCode(); 
    if (HttpResult == HttpURLConnection.HTTP_OK) { 
     BufferedReader br = new BufferedReader(new InputStreamReader(
       urlConnection.getInputStream(), "utf-8")); 
     String line = null; 
     while ((line = br.readLine()) != null) { 
      sb.append(line + "\n"); 
     } 
     br.close(); 
     result = CommonMethods.parseJsonToArray(sb.toString()); 

    } else { 
     System.out.println("*** RESPONSE MESSAGE ***"); 
     System.out.println(urlConnection.getResponseMessage()); 
    } 
    return result; 
} catch (MalformedURLException e) { 

    e.printStackTrace(); 
} catch (IOException e) { 

    e.printStackTrace(); 
} finally { 
    if (urlConnection != null) 
     urlConnection.disconnect(); 
} 
return null; 
} 

C# Servicecode:
Service:

public Result UploadUserProfilePicture(FileToUpload image) 
    { 
     try 
     { 
      byte[] bytes = Convert.FromBase64String(image.File); 

      FileType fileType = bytes.GetFileType(); 

      Guid guid = Guid.NewGuid(); 
      string imageName = guid.ToString() + "." + fileType.Extension; 
      var path = Path.Combine(@"C:\UploadedImages\" + imageName); 

      File.WriteAllBytes(path, bytes); 

      return new Result 
      { 
       Success = true, 
       Message = imageName 
      }; 
     } 
     catch(Exception ex) 
     { 
      return new Result 
      { 
       Success = false, 
       Message = ex.ToString() 
      }; 
     } 
    } 

IService:

[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
[OperationContract] 
Result UploadUserProfilePicture(FileToUpload image); 

Web.Config auf Service:
Ich bekam einen 400-Fehler Bad Anfrage ohne unten.

<bindings> 
    <webHttpBinding> 
<binding 
    name="binding" 
    openTimeout="00:10:00" closeTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" 
      maxBufferPoolSize="2147483647" 
      maxReceivedMessageSize="2147483647" 
      maxBufferSize="2147483647" transferMode="Streamed"> 
    <readerQuotas maxDepth="250000000" maxStringContentLength="250000000" maxArrayLength="250000000" maxBytesPerRead="250000000" maxNameTableCharCount="250000000"/> 
    <security mode="None" /> 
     </binding> 
    </webHttpBinding> 
</bindings> 
1

Ohne dies jemals in Kombination mit Android/WCF REST versucht zu haben, gibt es ein paar Dinge, die ich in Ihrem Code bemerke.

Zuerst sagen Sie im Betriebsvertrag, dass Ihre REST-Methode JSON erwartet und JSON zurückgibt. Aber der Android-Code ist nicht Senden JSON. Es sendet nur den Inhalt der Eingabedatei unverändert. Das ist eine Sache, die ich für falsch halte. Der Code, den Sie verwenden, ist gut, wenn Sie etwas auf eine Website hochladen möchten, so wie es ein Browser-Formular tun würde, aber das ist nicht das Gleiche wie die Verwendung einer REST-Anfrage.

Die andere Sache ist: Ihre REST-Methode würde keinen Stream Parameter nehmen, da es keinen Strom erhält.

Das erste, was ich tun würde, ist die Methode REST POST so auszugestalten, dass es ein JSON-Objekt wie folgt akzeptiert:

{ imageBytes = "0dac...." } 

mit dem imageBytes ist eine Base64-codierte Version des Bildes, das Sie speichern möchten (zum Beispiel: die Bytes einer PNG-Datei base64 codiert). Sie können dann andere Mittel verwenden, um zu testen, ob das gut funktioniert.

Dann würde ich den Android-Code ändern, so dass es

  1. die Datei Liest gesendet und erstellt eine Base64-codierte Version davon zu sein.
  2. Sendet diese Base64-codierte Version in einem JSON-Objekt wie oben beschrieben.

Dann sollten die Dinge funktionieren. Wie ich oben gesagt habe, habe ich das vorher nicht selbst in dieser Kombination gemacht, also gibt es keinen Beispielcode, den ich Ihnen geben kann.